xref: /llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision f75860f89522453f361e1ef54d7a33be2a2d75b1)
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_v8bf16 :
149    ComplexPattern<v4bf16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
150def extract_high_v4f32 :
151    ComplexPattern<v2f32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
152def extract_high_v2f64 :
153    ComplexPattern<v1f64, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
154
155def gi_extract_high_v8f16 :
156  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
157  GIComplexPatternEquiv<extract_high_v8f16>;
158def gi_extract_high_v4f32 :
159  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
160  GIComplexPatternEquiv<extract_high_v4f32>;
161
162def extract_high_dup_v8i16 :
163   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
164def extract_high_dup_v4i32 :
165   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
166
167def dup_v8i16 :
168    PatFrags<(ops node:$LHS, node:$RHS),
169             [(v4i16 (extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 0))),
170              (v4i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS))]>;
171def dup_v4i32 :
172    PatFrags<(ops node:$LHS, node:$RHS),
173             [(v2i32 (extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 0))),
174              (v2i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS))]>;
175def dup_v8f16 :
176    PatFrags<(ops node:$LHS, node:$RHS),
177             [(v4f16 (extract_subvector (v8f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS)), (i64 0))),
178              (v4f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS))]>;
179def dup_v4f32 :
180    PatFrags<(ops node:$LHS, node:$RHS),
181             [(v2f32 (extract_subvector (v4f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS)), (i64 0))),
182              (v2f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS))]>;
183
184// Match either a scalar_to_vector (from SDAG) or a vector_insert of undef (from GISel)
185def vec_ins_or_scal_vec : PatFrags<(ops node:$src),
186                          [(vector_insert undef, node:$src, (i64 0)),
187                           (scalar_to_vector node:$src)]>;
188
189//===----------------------------------------------------------------------===//
190// Asm Operand Classes.
191//
192
193// Shifter operand for arithmetic shifted encodings.
194def ShifterOperand : AsmOperandClass {
195  let Name = "Shifter";
196}
197
198// Shifter operand for mov immediate encodings.
199def MovImm32ShifterOperand : AsmOperandClass {
200  let SuperClasses = [ShifterOperand];
201  let Name = "MovImm32Shifter";
202  let RenderMethod = "addShifterOperands";
203  let DiagnosticType = "InvalidMovImm32Shift";
204}
205def MovImm64ShifterOperand : AsmOperandClass {
206  let SuperClasses = [ShifterOperand];
207  let Name = "MovImm64Shifter";
208  let RenderMethod = "addShifterOperands";
209  let DiagnosticType = "InvalidMovImm64Shift";
210}
211
212// Shifter operand for arithmetic register shifted encodings.
213class ArithmeticShifterOperand<int width> : AsmOperandClass {
214  let SuperClasses = [ShifterOperand];
215  let Name = "ArithmeticShifter" # width;
216  let PredicateMethod = "isArithmeticShifter<" # width # ">";
217  let RenderMethod = "addShifterOperands";
218  let DiagnosticType = "AddSubRegShift" # width;
219}
220
221def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
222def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
223
224// Shifter operand for logical register shifted encodings.
225class LogicalShifterOperand<int width> : AsmOperandClass {
226  let SuperClasses = [ShifterOperand];
227  let Name = "LogicalShifter" # width;
228  let PredicateMethod = "isLogicalShifter<" # width # ">";
229  let RenderMethod = "addShifterOperands";
230  let DiagnosticType = "AddSubRegShift" # width;
231}
232
233def LogicalShifterOperand32 : LogicalShifterOperand<32>;
234def LogicalShifterOperand64 : LogicalShifterOperand<64>;
235
236// Shifter operand for logical vector 128/64-bit shifted encodings.
237def LogicalVecShifterOperand : AsmOperandClass {
238  let SuperClasses = [ShifterOperand];
239  let Name = "LogicalVecShifter";
240  let RenderMethod = "addShifterOperands";
241}
242def LogicalVecHalfWordShifterOperand : AsmOperandClass {
243  let SuperClasses = [LogicalVecShifterOperand];
244  let Name = "LogicalVecHalfWordShifter";
245  let RenderMethod = "addShifterOperands";
246}
247
248// The "MSL" shifter on the vector MOVI instruction.
249def MoveVecShifterOperand : AsmOperandClass {
250  let SuperClasses = [ShifterOperand];
251  let Name = "MoveVecShifter";
252  let RenderMethod = "addShifterOperands";
253}
254
255// Extend operand for arithmetic encodings.
256def ExtendOperand : AsmOperandClass {
257  let Name = "Extend";
258  let DiagnosticType = "AddSubRegExtendLarge";
259}
260def ExtendOperand64 : AsmOperandClass {
261  let SuperClasses = [ExtendOperand];
262  let Name = "Extend64";
263  let DiagnosticType = "AddSubRegExtendSmall";
264}
265// 'extend' that's a lsl of a 64-bit register.
266def ExtendOperandLSL64 : AsmOperandClass {
267  let SuperClasses = [ExtendOperand];
268  let Name = "ExtendLSL64";
269  let RenderMethod = "addExtend64Operands";
270  let DiagnosticType = "AddSubRegExtendLarge";
271}
272
273// 8-bit floating-point immediate encodings.
274def FPImmOperand : AsmOperandClass {
275  let Name = "FPImm";
276  let ParserMethod = "tryParseFPImm<true>";
277  let DiagnosticType = "InvalidFPImm";
278}
279
280def CondCode : AsmOperandClass {
281  let Name = "CondCode";
282  let DiagnosticType = "InvalidCondCode";
283}
284
285// A 32-bit register pasrsed as 64-bit
286def GPR32as64Operand : AsmOperandClass {
287  let Name = "GPR32as64";
288  let ParserMethod =
289      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
290}
291def GPR32as64 : RegisterOperand<GPR32> {
292  let ParserMatchClass = GPR32as64Operand;
293}
294
295// A 64-bit register pasrsed as 32-bit
296def GPR64as32Operand : AsmOperandClass {
297  let Name = "GPR64as32";
298  let ParserMethod =
299      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
300}
301def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
302  let ParserMatchClass = GPR64as32Operand;
303}
304
305// 8-bit immediate for AdvSIMD where 64-bit values of the form:
306// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
307// are encoded as the eight bit value 'abcdefgh'.
308def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
309
310class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
311  let Name = "UImm" # Width # "s" # Scale;
312  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
313  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
314  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
315}
316
317class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
318  let Name = "SImm" # Width # "s" # Scale;
319  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
320  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
321  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
322}
323
324//===----------------------------------------------------------------------===//
325// Operand Definitions.
326//
327
328// ADR[P] instruction labels.
329def AdrpOperand : AsmOperandClass {
330  let Name = "AdrpLabel";
331  let ParserMethod = "tryParseAdrpLabel";
332  let DiagnosticType = "InvalidLabel";
333}
334def adrplabel : Operand<i64> {
335  let EncoderMethod = "getAdrLabelOpValue";
336  let PrintMethod = "printAdrAdrpLabel";
337  let ParserMatchClass = AdrpOperand;
338  let OperandType = "OPERAND_PCREL";
339}
340
341def AdrOperand : AsmOperandClass {
342  let Name = "AdrLabel";
343  let ParserMethod = "tryParseAdrLabel";
344  let DiagnosticType = "InvalidLabel";
345}
346def adrlabel : Operand<i64> {
347  let EncoderMethod = "getAdrLabelOpValue";
348  let PrintMethod = "printAdrAdrpLabel";
349  let ParserMatchClass = AdrOperand;
350  let OperandType = "OPERAND_PCREL";
351}
352
353class SImmOperand<int width> : AsmOperandClass {
354  let Name = "SImm" # width;
355  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
356  let RenderMethod = "addImmOperands";
357  let PredicateMethod = "isSImm<" # width # ">";
358}
359
360class AsmImmRange<int Low, int High> : AsmOperandClass {
361  let Name = "Imm" # Low # "_" # High;
362  let DiagnosticType = "InvalidImm" # Low # "_" # High;
363  let RenderMethod = "addImmOperands";
364  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
365}
366
367// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
368def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
369def simm10Scaled : Operand<i64> {
370  let ParserMatchClass = SImm10s8Operand;
371  let DecoderMethod = "DecodeSImm<10>";
372  let PrintMethod = "printImmScale<8>";
373}
374
375def simm9s16 : Operand<i64> {
376  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
377  let DecoderMethod = "DecodeSImm<9>";
378  let PrintMethod = "printImmScale<16>";
379}
380
381// uimm6 predicate - True if the immediate is in the range [0, 63].
382def UImm6Operand : AsmOperandClass {
383  let Name = "UImm6";
384  let DiagnosticType = "InvalidImm0_63";
385}
386
387def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
388  let ParserMatchClass = UImm6Operand;
389}
390
391def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
392  let ParserMatchClass = AsmImmRange<0, 65535>;
393}
394
395def uimm6_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
396    let ParserMatchClass = UImm6Operand;
397}
398
399def uimm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 64; }]> {
400   let ParserMatchClass = UImm6Operand;
401}
402
403def UImm6Plus1Operand : AsmOperandClass {
404  let Name = "UImm6P1";
405  let DiagnosticType = "InvalidImm1_64";
406  let RenderMethod = "addImmOperands";
407  let ParserMethod = "tryParseAdjImm0_63<-1>";
408  let PredicateMethod = "isImmInRange<0,63>";
409}
410
411def UImm6Minus1Operand : AsmOperandClass {
412  let Name = "UImm6M1";
413  let DiagnosticType = "InvalidImmM1_62";
414  let RenderMethod = "addImmOperands";
415  let ParserMethod = "tryParseAdjImm0_63<1>";
416  let PredicateMethod = "isImmInRange<0,63>";
417}
418
419def uimm6p1_32b : Operand<i32> {
420  let ParserMatchClass = UImm6Plus1Operand;
421}
422
423def uimm6p1_64b : Operand<i64> {
424  let ParserMatchClass = UImm6Plus1Operand;
425}
426
427def uimm6m1_32b : Operand<i32> {
428  let ParserMatchClass = UImm6Minus1Operand;
429}
430
431def uimm6m1_64b : Operand<i64> {
432  let ParserMatchClass = UImm6Minus1Operand;
433}
434
435def SImm9Operand : SImmOperand<9>;
436def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
437  let ParserMatchClass = SImm9Operand;
438  let DecoderMethod = "DecodeSImm<9>";
439}
440
441// imm0_255 predicate - True if the immediate is in the range [0,255].
442def Imm0_255Operand : AsmImmRange<0,255>;
443
444def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
445  let ParserMatchClass = Imm0_255Operand;
446}
447def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
448  let ParserMatchClass = Imm0_255Operand;
449}
450
451def SImm8Operand : SImmOperand<8>;
452def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
453  let ParserMatchClass = SImm8Operand;
454  let DecoderMethod = "DecodeSImm<8>";
455}
456def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
457  let ParserMatchClass = SImm8Operand;
458  let DecoderMethod = "DecodeSImm<8>";
459}
460
461def SImm6Operand : SImmOperand<6>;
462def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
463  let ParserMatchClass = SImm6Operand;
464  let DecoderMethod = "DecodeSImm<6>";
465}
466
467def SImm5Operand : SImmOperand<5>;
468def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
469  let ParserMatchClass = SImm5Operand;
470  let DecoderMethod = "DecodeSImm<5>";
471}
472
473def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
474  let ParserMatchClass = SImm5Operand;
475  let DecoderMethod = "DecodeSImm<5>";
476}
477
478def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
479  let ParserMatchClass = SImm5Operand;
480  let DecoderMethod = "DecodeSImm<5>";
481  let PrintMethod = "printSImm<8>";
482}
483
484def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
485  let ParserMatchClass = SImm5Operand;
486  let DecoderMethod = "DecodeSImm<5>";
487  let PrintMethod = "printSImm<16>";
488}
489
490// simm7sN predicate - True if the immediate is a multiple of N in the range
491// [-64 * N, 63 * N].
492
493def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
494def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
495def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
496
497def simm7s4 : Operand<i32> {
498  let ParserMatchClass = SImm7s4Operand;
499  let PrintMethod = "printImmScale<4>";
500}
501
502def simm7s8 : Operand<i32> {
503  let ParserMatchClass = SImm7s8Operand;
504  let PrintMethod = "printImmScale<8>";
505}
506
507def simm7s16 : Operand<i32> {
508  let ParserMatchClass = SImm7s16Operand;
509  let PrintMethod = "printImmScale<16>";
510}
511
512def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
513
514def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
515def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
516def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
517def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
518def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
519
520def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
521def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
522
523def UImmS1XForm : SDNodeXForm<imm, [{
524  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
525}]>;
526def UImmS2XForm : SDNodeXForm<imm, [{
527  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
528}]>;
529def UImmS4XForm : SDNodeXForm<imm, [{
530  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
531}]>;
532def UImmS8XForm : SDNodeXForm<imm, [{
533  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
534}]>;
535
536def UImmM2XForm : SDNodeXForm<imm, [{
537  return CurDAG->getTargetConstant(N->getZExtValue() * 2, SDLoc(N), MVT::i32);
538}]>;
539
540def UImmM4XForm : SDNodeXForm<imm, [{
541  return CurDAG->getTargetConstant(N->getZExtValue() * 4, SDLoc(N), MVT::i32);
542}]>;
543
544def UImmM8XForm : SDNodeXForm<imm, [{
545  return CurDAG->getTargetConstant(N->getZExtValue() * 8, SDLoc(N), MVT::i32);
546}]>;
547
548// uimm5sN predicate - True if the immediate is a multiple of N in the range
549// [0 * N, 32 * N].
550def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
551def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
552def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
553
554def uimm5s2 : Operand<i64>, ImmLeaf<i64,
555                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
556                UImmS2XForm> {
557  let ParserMatchClass = UImm5s2Operand;
558  let PrintMethod = "printImmScale<2>";
559}
560def uimm5s4 : Operand<i64>, ImmLeaf<i64,
561                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
562                UImmS4XForm> {
563  let ParserMatchClass = UImm5s4Operand;
564  let PrintMethod = "printImmScale<4>";
565}
566def uimm5s8 : Operand<i64>, ImmLeaf<i64,
567                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
568                UImmS8XForm> {
569  let ParserMatchClass = UImm5s8Operand;
570  let PrintMethod = "printImmScale<8>";
571}
572
573// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
574// instead of ImmLeaf (Constant)
575def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
576                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
577                UImmS2XForm> {
578  let ParserMatchClass = UImm5s2Operand;
579  let PrintMethod = "printImmScale<2>";
580}
581def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
582                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
583                UImmS4XForm> {
584  let ParserMatchClass = UImm5s4Operand;
585  let PrintMethod = "printImmScale<4>";
586}
587def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
588                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
589                UImmS8XForm> {
590  let ParserMatchClass = UImm5s8Operand;
591  let PrintMethod = "printImmScale<8>";
592}
593
594// uimm6sN predicate - True if the immediate is a multiple of N in the range
595// [0 * N, 64 * N].
596def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
597def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
598def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
599def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
600def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
601
602def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
603  let ParserMatchClass = UImm6s1Operand;
604}
605def uimm6s2 : Operand<i64>, ImmLeaf<i64,
606[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
607  let PrintMethod = "printImmScale<2>";
608  let ParserMatchClass = UImm6s2Operand;
609}
610def uimm6s4 : Operand<i64>, ImmLeaf<i64,
611[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
612  let PrintMethod = "printImmScale<4>";
613  let ParserMatchClass = UImm6s4Operand;
614}
615def uimm6s8 : Operand<i64>, ImmLeaf<i64,
616[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
617  let PrintMethod = "printImmScale<8>";
618  let ParserMatchClass = UImm6s8Operand;
619}
620def uimm6s16 : Operand<i64>, ImmLeaf<i64,
621[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
622  let PrintMethod = "printImmScale<16>";
623  let ParserMatchClass = UImm6s16Operand;
624}
625
626def SImmS2XForm : SDNodeXForm<imm, [{
627  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
628}]>;
629def SImmS3XForm : SDNodeXForm<imm, [{
630  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
631}]>;
632def SImmS4XForm : SDNodeXForm<imm, [{
633  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
634}]>;
635def SImmS16XForm : SDNodeXForm<imm, [{
636  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
637}]>;
638def SImmS32XForm : SDNodeXForm<imm, [{
639  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
640}]>;
641
642// simm6sN predicate - True if the immediate is a multiple of N in the range
643// [-32 * N, 31 * N].
644def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
645def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
646  let ParserMatchClass = SImm6s1Operand;
647  let DecoderMethod = "DecodeSImm<6>";
648}
649
650// simm4sN predicate - True if the immediate is a multiple of N in the range
651// [ -8* N, 7 * N].
652def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
653def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
654def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
655def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
656def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
657def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
658
659def simm4s1 : Operand<i64>, ImmLeaf<i64,
660[{ return Imm >=-8  && Imm <= 7; }]> {
661  let ParserMatchClass = SImm4s1Operand;
662  let DecoderMethod = "DecodeSImm<4>";
663}
664
665def simm4s2 : Operand<i64>, ImmLeaf<i64,
666[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
667  let PrintMethod = "printImmScale<2>";
668  let ParserMatchClass = SImm4s2Operand;
669  let DecoderMethod = "DecodeSImm<4>";
670}
671
672def simm4s3 : Operand<i64>, ImmLeaf<i64,
673[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
674  let PrintMethod = "printImmScale<3>";
675  let ParserMatchClass = SImm4s3Operand;
676  let DecoderMethod = "DecodeSImm<4>";
677}
678
679def simm4s4 : Operand<i64>, ImmLeaf<i64,
680[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
681  let PrintMethod = "printImmScale<4>";
682  let ParserMatchClass = SImm4s4Operand;
683  let DecoderMethod = "DecodeSImm<4>";
684}
685def simm4s16 : Operand<i64>, ImmLeaf<i64,
686[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
687  let PrintMethod = "printImmScale<16>";
688  let ParserMatchClass = SImm4s16Operand;
689  let DecoderMethod = "DecodeSImm<4>";
690}
691def simm4s32 : Operand<i64>, ImmLeaf<i64,
692[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
693  let PrintMethod = "printImmScale<32>";
694  let ParserMatchClass = SImm4s32Operand;
695  let DecoderMethod = "DecodeSImm<4>";
696}
697
698def Imm1_8Operand : AsmImmRange<1, 8>;
699def Imm1_16Operand : AsmImmRange<1, 16>;
700def Imm1_32Operand : AsmImmRange<1, 32>;
701def Imm1_64Operand : AsmImmRange<1, 64>;
702
703class BranchTarget<int N> : AsmOperandClass {
704  let Name = "BranchTarget" # N;
705  let DiagnosticType = "InvalidLabel";
706  let PredicateMethod = "isBranchTarget<" # N # ">";
707}
708
709class PCRelLabel<int N> : BranchTarget<N> {
710  let Name = "PCRelLabel" # N;
711}
712
713def BranchTarget14Operand : BranchTarget<14>;
714def BranchTarget26Operand : BranchTarget<26>;
715def PCRelLabel19Operand   : PCRelLabel<19>;
716def PCRelLabel9Operand    : PCRelLabel<9>;
717
718def MovWSymbolG3AsmOperand : AsmOperandClass {
719  let Name = "MovWSymbolG3";
720  let RenderMethod = "addImmOperands";
721}
722
723def movw_symbol_g3 : Operand<i32> {
724  let ParserMatchClass = MovWSymbolG3AsmOperand;
725}
726
727def MovWSymbolG2AsmOperand : AsmOperandClass {
728  let Name = "MovWSymbolG2";
729  let RenderMethod = "addImmOperands";
730}
731
732def movw_symbol_g2 : Operand<i32> {
733  let ParserMatchClass = MovWSymbolG2AsmOperand;
734}
735
736def MovWSymbolG1AsmOperand : AsmOperandClass {
737  let Name = "MovWSymbolG1";
738  let RenderMethod = "addImmOperands";
739}
740
741def movw_symbol_g1 : Operand<i32> {
742  let ParserMatchClass = MovWSymbolG1AsmOperand;
743}
744
745def MovWSymbolG0AsmOperand : AsmOperandClass {
746  let Name = "MovWSymbolG0";
747  let RenderMethod = "addImmOperands";
748}
749
750def movw_symbol_g0 : Operand<i32> {
751  let ParserMatchClass = MovWSymbolG0AsmOperand;
752}
753
754class fixedpoint_i32<ValueType FloatVT>
755  : Operand<FloatVT>,
756    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
757  let EncoderMethod = "getFixedPointScaleOpValue";
758  let DecoderMethod = "DecodeFixedPointScaleImm32";
759  let ParserMatchClass = Imm1_32Operand;
760}
761
762class fixedpoint_i64<ValueType FloatVT>
763  : Operand<FloatVT>,
764    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
765  let EncoderMethod = "getFixedPointScaleOpValue";
766  let DecoderMethod = "DecodeFixedPointScaleImm64";
767  let ParserMatchClass = Imm1_64Operand;
768}
769
770def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
771def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
772def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
773
774def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
775def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
776def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
777
778class fixedpoint_recip_i32<ValueType FloatVT>
779  : Operand<FloatVT>,
780    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<32>", [fpimm, ld]> {
781  let EncoderMethod = "getFixedPointScaleOpValue";
782  let DecoderMethod = "DecodeFixedPointScaleImm32";
783}
784
785class fixedpoint_recip_i64<ValueType FloatVT>
786  : Operand<FloatVT>,
787    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<64>", [fpimm, ld]> {
788  let EncoderMethod = "getFixedPointScaleOpValue";
789  let DecoderMethod = "DecodeFixedPointScaleImm64";
790}
791
792def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32<f16>;
793def fixedpoint_recip_f32_i32 : fixedpoint_recip_i32<f32>;
794def fixedpoint_recip_f64_i32 : fixedpoint_recip_i32<f64>;
795
796def fixedpoint_recip_f16_i64 : fixedpoint_recip_i64<f16>;
797def fixedpoint_recip_f32_i64 : fixedpoint_recip_i64<f32>;
798def fixedpoint_recip_f64_i64 : fixedpoint_recip_i64<f64>;
799
800def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
801  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
802}]> {
803  let EncoderMethod = "getVecShiftR8OpValue";
804  let DecoderMethod = "DecodeVecShiftR8Imm";
805  let ParserMatchClass = Imm1_8Operand;
806}
807def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
808  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
809}]> {
810  let EncoderMethod = "getVecShiftR16OpValue";
811  let DecoderMethod = "DecodeVecShiftR16Imm";
812  let ParserMatchClass = Imm1_16Operand;
813}
814def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
815  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
816}]> {
817  let EncoderMethod = "getVecShiftR16OpValue";
818  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
819  let ParserMatchClass = Imm1_8Operand;
820}
821def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
822  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
823}]> {
824  let EncoderMethod = "getVecShiftR32OpValue";
825  let DecoderMethod = "DecodeVecShiftR32Imm";
826  let ParserMatchClass = Imm1_32Operand;
827}
828def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
829  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
830}]> {
831  let EncoderMethod = "getVecShiftR32OpValue";
832  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
833  let ParserMatchClass = Imm1_16Operand;
834}
835def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
836  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
837}]> {
838  let EncoderMethod = "getVecShiftR64OpValue";
839  let DecoderMethod = "DecodeVecShiftR64Imm";
840  let ParserMatchClass = Imm1_64Operand;
841}
842def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
843  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
844}]> {
845  let EncoderMethod = "getVecShiftR64OpValue";
846  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
847  let ParserMatchClass = Imm1_32Operand;
848}
849
850// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
851// (ImmLeaf)
852def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
853  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
854}]> {
855  let EncoderMethod = "getVecShiftR8OpValue";
856  let DecoderMethod = "DecodeVecShiftR8Imm";
857  let ParserMatchClass = Imm1_8Operand;
858}
859def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
860  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
861}]> {
862  let EncoderMethod = "getVecShiftR16OpValue";
863  let DecoderMethod = "DecodeVecShiftR16Imm";
864  let ParserMatchClass = Imm1_16Operand;
865}
866def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
867  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
868}]> {
869  let EncoderMethod = "getVecShiftR32OpValue";
870  let DecoderMethod = "DecodeVecShiftR32Imm";
871  let ParserMatchClass = Imm1_32Operand;
872}
873def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
874  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
875}]> {
876  let EncoderMethod = "getVecShiftR64OpValue";
877  let DecoderMethod = "DecodeVecShiftR64Imm";
878  let ParserMatchClass = Imm1_64Operand;
879}
880
881def Imm0_0Operand : AsmImmRange<0, 0>;
882def Imm0_1Operand : AsmImmRange<0, 1>;
883def Imm1_1Operand : AsmImmRange<1, 1>;
884def Imm0_3Operand : AsmImmRange<0, 3>;
885def Imm1_3Operand : AsmImmRange<1, 3>;
886def Imm0_7Operand : AsmImmRange<0, 7>;
887def Imm1_7Operand : AsmImmRange<1, 7>;
888def Imm0_15Operand : AsmImmRange<0, 15>;
889def Imm0_31Operand : AsmImmRange<0, 31>;
890def Imm0_63Operand : AsmImmRange<0, 63>;
891
892def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
893  return (((uint32_t)Imm) < 8);
894}]> {
895  let EncoderMethod = "getVecShiftL8OpValue";
896  let DecoderMethod = "DecodeVecShiftL8Imm";
897  let ParserMatchClass = Imm0_7Operand;
898}
899def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
900  return (((uint32_t)Imm) < 16);
901}]> {
902  let EncoderMethod = "getVecShiftL16OpValue";
903  let DecoderMethod = "DecodeVecShiftL16Imm";
904  let ParserMatchClass = Imm0_15Operand;
905}
906def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
907  return (((uint32_t)Imm) < 32);
908}]> {
909  let EncoderMethod = "getVecShiftL32OpValue";
910  let DecoderMethod = "DecodeVecShiftL32Imm";
911  let ParserMatchClass = Imm0_31Operand;
912}
913def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
914  return (((uint32_t)Imm) < 64);
915}]> {
916  let EncoderMethod = "getVecShiftL64OpValue";
917  let DecoderMethod = "DecodeVecShiftL64Imm";
918  let ParserMatchClass = Imm0_63Operand;
919}
920
921// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
922// (ImmLeaf)
923def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
924  return (((uint32_t)Imm) < 8);
925}]> {
926  let EncoderMethod = "getVecShiftL8OpValue";
927  let DecoderMethod = "DecodeVecShiftL8Imm";
928  let ParserMatchClass = Imm0_7Operand;
929}
930def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
931  return (((uint32_t)Imm) < 16);
932}]> {
933  let EncoderMethod = "getVecShiftL16OpValue";
934  let DecoderMethod = "DecodeVecShiftL16Imm";
935  let ParserMatchClass = Imm0_15Operand;
936}
937def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
938  return (((uint32_t)Imm) < 32);
939}]> {
940  let EncoderMethod = "getVecShiftL32OpValue";
941  let DecoderMethod = "DecodeVecShiftL32Imm";
942  let ParserMatchClass = Imm0_31Operand;
943}
944def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
945  return (((uint32_t)Imm) < 64);
946}]> {
947  let EncoderMethod = "getVecShiftL64OpValue";
948  let DecoderMethod = "DecodeVecShiftL64Imm";
949  let ParserMatchClass = Imm0_63Operand;
950}
951
952// Crazy immediate formats used by 32-bit and 64-bit logical immediate
953// instructions for splatting repeating bit patterns across the immediate.
954def logical_imm32_XFORM : SDNodeXForm<imm, [{
955  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
956  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
957}]>;
958def logical_imm64_XFORM : SDNodeXForm<imm, [{
959  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
960  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
961}]>;
962
963def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
964  GISDNodeXFormEquiv<logical_imm32_XFORM>;
965def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
966  GISDNodeXFormEquiv<logical_imm64_XFORM>;
967
968let DiagnosticType = "LogicalSecondSource" in {
969  def LogicalImm32Operand : AsmOperandClass {
970    let Name = "LogicalImm32";
971    let PredicateMethod = "isLogicalImm<int32_t>";
972    let RenderMethod = "addLogicalImmOperands<int32_t>";
973  }
974  def LogicalImm64Operand : AsmOperandClass {
975    let Name = "LogicalImm64";
976    let PredicateMethod = "isLogicalImm<int64_t>";
977    let RenderMethod = "addLogicalImmOperands<int64_t>";
978  }
979  def LogicalImm32NotOperand : AsmOperandClass {
980    let Name = "LogicalImm32Not";
981    let PredicateMethod = "isLogicalImm<int32_t>";
982    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
983  }
984  def LogicalImm64NotOperand : AsmOperandClass {
985    let Name = "LogicalImm64Not";
986    let PredicateMethod = "isLogicalImm<int64_t>";
987    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
988  }
989}
990
991def Imm0_127Operand : AsmImmRange<0, 127>;
992
993let OperandType = "OPERAND_IMMEDIATE" in {
994
995def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
996  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
997}], logical_imm32_XFORM> {
998  let PrintMethod = "printLogicalImm<int32_t>";
999  let ParserMatchClass = LogicalImm32Operand;
1000}
1001def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
1002  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
1003}], logical_imm64_XFORM> {
1004  let PrintMethod = "printLogicalImm<int64_t>";
1005  let ParserMatchClass = LogicalImm64Operand;
1006}
1007def logical_imm32_not : Operand<i32> {
1008  let ParserMatchClass = LogicalImm32NotOperand;
1009}
1010def logical_imm64_not : Operand<i64> {
1011  let ParserMatchClass = LogicalImm64NotOperand;
1012}
1013
1014// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
1015let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
1016def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
1017  return ((uint32_t)Imm) < 65536;
1018}]>;
1019
1020def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
1021  return ((uint64_t)Imm) < 65536;
1022}]>;
1023
1024def imm64_0_65535 : Operand<i64>, ImmLeaf<i64, [{
1025  return ((uint64_t)Imm) < 65536;
1026}]>;
1027} // ParserMatchClass
1028
1029def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
1030  return ((uint32_t)Imm) < 256;
1031}]> {
1032  let ParserMatchClass = Imm0_255Operand;
1033  let PrintMethod = "printImm";
1034}
1035
1036// imm0_127 predicate - True if the immediate is in the range [0,127]
1037def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
1038  return ((uint32_t)Imm) < 128;
1039}]> {
1040  let ParserMatchClass = Imm0_127Operand;
1041  let PrintMethod = "printImm";
1042}
1043
1044def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
1045  return ((uint64_t)Imm) < 128;
1046}]> {
1047  let ParserMatchClass = Imm0_127Operand;
1048  let PrintMethod = "printImm";
1049}
1050
1051// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
1052// for all shift-amounts.
1053
1054// imm0_63 predicate - True if the immediate is in the range [0,63]
1055def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
1056  return ((uint64_t)Imm) < 64;
1057}]> {
1058  let ParserMatchClass = Imm0_63Operand;
1059}
1060
1061def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
1062  return ((uint64_t)Imm) < 64;
1063}]> {
1064  let ParserMatchClass = Imm0_63Operand;
1065}
1066
1067// imm0_31 predicate - True if the immediate is in the range [0,31]
1068def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
1069  return ((uint64_t)Imm) < 32;
1070}]> {
1071  let ParserMatchClass = Imm0_31Operand;
1072}
1073
1074// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
1075// instead of Constant (ImmLeaf)
1076def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
1077  return ((uint64_t)Imm) < 32;
1078}]> {
1079  let ParserMatchClass = Imm0_31Operand;
1080}
1081
1082// True if the 32-bit immediate is in the range [0,31]
1083def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
1084  return ((uint64_t)Imm) < 32;
1085}]> {
1086  let ParserMatchClass = Imm0_31Operand;
1087}
1088
1089// imm0_1 predicate - True if the immediate is in the range [0,1]
1090def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
1091  return ((uint64_t)Imm) < 2;
1092}]> {
1093  let ParserMatchClass = Imm0_1Operand;
1094}
1095
1096// timm0_1 - as above, but use TargetConstant (TImmLeaf)
1097def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
1098  return ((uint64_t)Imm) < 2;
1099}]> {
1100  let ParserMatchClass = Imm0_1Operand;
1101}
1102
1103// timm32_0_0 predicate - True if the 32-bit immediate is in the range [0,0]
1104def timm32_0_0 : Operand<i32>, TImmLeaf<i32, [{
1105  return ((uint32_t)Imm) == 0;
1106}]> {
1107  let ParserMatchClass = Imm0_0Operand;
1108}
1109
1110// timm32_0_1 predicate - True if the 32-bit immediate is in the range [0,1]
1111def timm32_0_1 : Operand<i32>, TImmLeaf<i32, [{
1112  return ((uint32_t)Imm) < 2;
1113}]> {
1114  let ParserMatchClass = Imm0_1Operand;
1115}
1116
1117// extq_timm32_0_1m8 - True if the 32-bit immediate is in the range [0,1], scale this immediate
1118// by a factor of 8 after a match is made.
1119def extq_timm32_0_1m8 : Operand<i32>, TImmLeaf<i32, [{
1120  return ((uint32_t)Imm) < 2;}], UImmM8XForm> {
1121  let ParserMatchClass = Imm0_15Operand;
1122}
1123
1124// timm32_1_1 - True if the 32-bit immediate is in the range [1,1]
1125def timm32_1_1 : Operand<i32>, TImmLeaf<i32, [{
1126    return ((uint32_t)Imm) == 1;
1127}]> {
1128  let ParserMatchClass = Imm1_1Operand;
1129}
1130
1131// timm32_1_3 predicate - True if the 32-bit immediate is in the range [1,3]
1132def timm32_1_3 : Operand<i32>, TImmLeaf<i32, [{
1133  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 4;
1134}]> {
1135  let ParserMatchClass = Imm1_3Operand;
1136}
1137
1138// imm0_15 predicate - True if the immediate is in the range [0,15]
1139def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
1140  return ((uint64_t)Imm) < 16;
1141}]> {
1142  let ParserMatchClass = Imm0_15Operand;
1143}
1144
1145// imm0_7 predicate - True if the immediate is in the range [0,7]
1146def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
1147  return ((uint64_t)Imm) < 8;
1148}]> {
1149  let ParserMatchClass = Imm0_7Operand;
1150}
1151
1152// imm0_3 predicate - True if the immediate is in the range [0,3]
1153def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
1154  return ((uint64_t)Imm) < 4;
1155}]> {
1156  let ParserMatchClass = Imm0_3Operand;
1157}
1158
1159// timm32_0_3 predicate - True if the 32-bit immediate is in the range [0,3]
1160def timm32_0_3 : Operand<i32>, TImmLeaf<i32, [{
1161  return ((uint32_t)Imm) < 4;
1162}]> {
1163  let ParserMatchClass = Imm0_3Operand;
1164}
1165
1166// extq_timm32_0_3m4 - True if the 32-bit immediate is in the range [0,3], scale this immediate
1167// by a factor of 4 after a match is made.
1168def extq_timm32_0_3m4 : Operand<i32>, TImmLeaf<i32, [{
1169  return ((uint32_t)Imm) < 4;}], UImmM4XForm> {
1170  let ParserMatchClass = Imm0_15Operand;
1171}
1172
1173// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1174def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
1175  return ((uint32_t)Imm) < 8;
1176}]> {
1177  let ParserMatchClass = Imm0_7Operand;
1178}
1179
1180// extq_timm32_0_7m2 - True if the 32-bit immediate is in the range [0,7], scale this immediate
1181// by a factor of 2 after a match is made.
1182def extq_timm32_0_7m2 : Operand<i32>, TImmLeaf<i32, [{
1183  return ((uint32_t)Imm) < 8;}], UImmM2XForm> {
1184  let ParserMatchClass = Imm0_15Operand;
1185}
1186
1187// timm32_1_7 predicate - True if the 32-bit immediate is in the range [1,7]
1188def timm32_1_7 : Operand<i32>, TImmLeaf<i32, [{
1189  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 8;
1190}]> {
1191  let ParserMatchClass = Imm1_7Operand;
1192}
1193
1194// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1195def imm32_0_7 : Operand<i32>, ImmLeaf<i32, [{
1196  return ((uint32_t)Imm) < 8;
1197}]> {
1198  let ParserMatchClass = Imm0_7Operand;
1199}
1200
1201// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1202def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
1203  return ((uint32_t)Imm) < 16;
1204}]> {
1205  let ParserMatchClass = Imm0_15Operand;
1206}
1207
1208// timm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1209def timm32_0_15 : Operand<i32>, TImmLeaf<i32, [{
1210  return ((uint32_t)Imm) < 16;
1211}]> {
1212  let ParserMatchClass = Imm0_15Operand;
1213}
1214
1215// timm32_0_31 predicate - True if the 32-bit immediate is in the range [0,31]
1216def timm32_0_31 : Operand<i32>, TImmLeaf<i32, [{
1217  return ((uint32_t)Imm) < 32;
1218}]> {
1219  let ParserMatchClass = Imm0_31Operand;
1220}
1221
1222// timm32_0_255 predicate - True if the 32-bit immediate is in the range [0,255]
1223def timm32_0_255 : Operand<i32>, TImmLeaf<i32, [{
1224  return ((uint32_t)Imm) < 256;
1225}]> {
1226  let ParserMatchClass = Imm0_255Operand;
1227}
1228
1229} // let OperandType = "OPERAND_IMMEDIATE"
1230
1231// An arithmetic shifter operand:
1232//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
1233//  {5-0} - imm6
1234class arith_shift<ValueType Ty, int width> : Operand<Ty> {
1235  let PrintMethod = "printShifter";
1236  let ParserMatchClass = !cast<AsmOperandClass>(
1237                         "ArithmeticShifterOperand" # width);
1238}
1239
1240def arith_shift32 : arith_shift<i32, 32>;
1241def arith_shift64 : arith_shift<i64, 64>;
1242
1243class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
1244    : Operand<Ty>,
1245      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
1246  let PrintMethod = "printShiftedRegister";
1247  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
1248}
1249
1250def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
1251def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
1252
1253def gi_arith_shifted_reg32 :
1254  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1255  GIComplexPatternEquiv<arith_shifted_reg32>;
1256
1257def gi_arith_shifted_reg64 :
1258  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1259  GIComplexPatternEquiv<arith_shifted_reg64>;
1260
1261// An arithmetic shifter operand:
1262//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1263//  {5-0} - imm6
1264class logical_shift<int width> : Operand<i32> {
1265  let PrintMethod = "printShifter";
1266  let ParserMatchClass = !cast<AsmOperandClass>(
1267                         "LogicalShifterOperand" # width);
1268}
1269
1270def logical_shift32 : logical_shift<32>;
1271def logical_shift64 : logical_shift<64>;
1272
1273class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1274    : Operand<Ty>,
1275      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1276  let PrintMethod = "printShiftedRegister";
1277  let MIOperandInfo = (ops regclass, shiftop);
1278}
1279
1280def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1281def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1282
1283def gi_logical_shifted_reg32 :
1284  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1285  GIComplexPatternEquiv<logical_shifted_reg32>;
1286
1287def gi_logical_shifted_reg64 :
1288  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1289  GIComplexPatternEquiv<logical_shifted_reg64>;
1290
1291// A logical vector shifter operand:
1292//  {7-6} - shift type: 00 = lsl
1293//  {5-0} - imm6: #0, #8, #16, or #24
1294def logical_vec_shift : Operand<i32> {
1295  let PrintMethod = "printShifter";
1296  let EncoderMethod = "getVecShifterOpValue";
1297  let ParserMatchClass = LogicalVecShifterOperand;
1298}
1299
1300// A logical vector half-word shifter operand:
1301//  {7-6} - shift type: 00 = lsl
1302//  {5-0} - imm6: #0 or #8
1303def logical_vec_hw_shift : Operand<i32> {
1304  let PrintMethod = "printShifter";
1305  let EncoderMethod = "getVecShifterOpValue";
1306  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1307}
1308
1309// A vector move shifter operand:
1310//  {0} - imm1: #8 or #16
1311def move_vec_shift : Operand<i32> {
1312  let PrintMethod = "printShifter";
1313  let EncoderMethod = "getMoveVecShifterOpValue";
1314  let ParserMatchClass = MoveVecShifterOperand;
1315}
1316
1317let DiagnosticType = "AddSubSecondSource" in {
1318  def AddSubImmOperand : AsmOperandClass {
1319    let Name = "AddSubImm";
1320    let ParserMethod = "tryParseImmWithOptionalShift";
1321    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1322  }
1323  def AddSubImmNegOperand : AsmOperandClass {
1324    let Name = "AddSubImmNeg";
1325    let ParserMethod = "tryParseImmWithOptionalShift";
1326    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1327  }
1328}
1329// An ADD/SUB immediate shifter operand:
1330//  second operand:
1331//  {7-6} - shift type: 00 = lsl
1332//  {5-0} - imm6: #0 or #12
1333class addsub_shifted_imm<ValueType Ty>
1334    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1335  let PrintMethod = "printAddSubImm";
1336  let EncoderMethod = "getAddSubImmOpValue";
1337  let ParserMatchClass = AddSubImmOperand;
1338  let MIOperandInfo = (ops i32imm, i32imm);
1339}
1340
1341class addsub_shifted_imm_neg<ValueType Ty>
1342    : Operand<Ty> {
1343  let EncoderMethod = "getAddSubImmOpValue";
1344  let ParserMatchClass = AddSubImmNegOperand;
1345  let MIOperandInfo = (ops i32imm, i32imm);
1346}
1347
1348def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1349def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1350def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1351def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1352
1353def gi_addsub_shifted_imm32 :
1354    GIComplexOperandMatcher<s32, "selectArithImmed">,
1355    GIComplexPatternEquiv<addsub_shifted_imm32>;
1356
1357def gi_addsub_shifted_imm64 :
1358    GIComplexOperandMatcher<s64, "selectArithImmed">,
1359    GIComplexPatternEquiv<addsub_shifted_imm64>;
1360
1361class neg_addsub_shifted_imm<ValueType Ty>
1362    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1363  let PrintMethod = "printAddSubImm";
1364  let EncoderMethod = "getAddSubImmOpValue";
1365  let ParserMatchClass = AddSubImmOperand;
1366  let MIOperandInfo = (ops i32imm, i32imm);
1367}
1368
1369def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1370def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1371
1372def gi_neg_addsub_shifted_imm32 :
1373    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1374    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1375
1376def gi_neg_addsub_shifted_imm64 :
1377    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1378    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1379
1380// An extend operand:
1381//  {5-3} - extend type
1382//  {2-0} - imm3
1383def arith_extend : Operand<i32> {
1384  let PrintMethod = "printArithExtend";
1385  let ParserMatchClass = ExtendOperand;
1386}
1387def arith_extend64 : Operand<i32> {
1388  let PrintMethod = "printArithExtend";
1389  let ParserMatchClass = ExtendOperand64;
1390}
1391
1392// 'extend' that's a lsl of a 64-bit register.
1393def arith_extendlsl64 : Operand<i32> {
1394  let PrintMethod = "printArithExtend";
1395  let ParserMatchClass = ExtendOperandLSL64;
1396}
1397
1398class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1399                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1400  let PrintMethod = "printExtendedRegister";
1401  let MIOperandInfo = (ops GPR32, arith_extend);
1402}
1403
1404class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1405                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1406  let PrintMethod = "printExtendedRegister";
1407  let MIOperandInfo = (ops GPR32, arith_extend64);
1408}
1409
1410def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1411def gi_arith_extended_reg32_i32 :
1412    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1413    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1414
1415def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1416def gi_arith_extended_reg32_i64 :
1417    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1418    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1419
1420def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1421def gi_arith_extended_reg32to64_i64 :
1422    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1423    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1424
1425def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1426
1427// Floating-point immediate.
1428
1429def fpimm16XForm : SDNodeXForm<fpimm, [{
1430      uint32_t Enc = AArch64_AM::getFP16Imm(N->getValueAPF());
1431      return CurDAG->getTargetConstant(Enc, SDLoc(N), MVT::i32);
1432    }]>;
1433
1434def fpimm32XForm : SDNodeXForm<fpimm, [{
1435      uint32_t Enc = AArch64_AM::getFP32Imm(N->getValueAPF());
1436      return CurDAG->getTargetConstant(Enc, SDLoc(N), MVT::i32);
1437    }]>;
1438
1439def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1440      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1441                                                          .bitcastToAPInt()
1442                                                          .getZExtValue());
1443      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1444    }]>;
1445
1446def fpimm64XForm : SDNodeXForm<fpimm, [{
1447      uint32_t Enc = AArch64_AM::getFP64Imm(N->getValueAPF());
1448      return CurDAG->getTargetConstant(Enc, SDLoc(N), MVT::i32);
1449    }]>;
1450
1451def fpimm16 : Operand<f16>,
1452              FPImmLeaf<f16, [{
1453      return AArch64_AM::getFP16Imm(Imm) != -1;
1454    }], fpimm16XForm> {
1455  let ParserMatchClass = FPImmOperand;
1456  let PrintMethod = "printFPImmOperand";
1457}
1458
1459def fpimmbf16 : Operand<bf16>,
1460                FPImmLeaf<bf16, [{
1461      return AArch64_AM::getFP16Imm(Imm) != -1;
1462    }], fpimm16XForm>;
1463
1464def fpimm32 : Operand<f32>,
1465              FPImmLeaf<f32, [{
1466      return AArch64_AM::getFP32Imm(Imm) != -1;
1467    }], fpimm32XForm> {
1468  let ParserMatchClass = FPImmOperand;
1469  let PrintMethod = "printFPImmOperand";
1470}
1471
1472def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1473      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1474      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1475    }], fpimm32SIMDModImmType4XForm> {
1476}
1477
1478def fpimm64 : Operand<f64>,
1479              FPImmLeaf<f64, [{
1480      return AArch64_AM::getFP64Imm(Imm) != -1;
1481    }], fpimm64XForm> {
1482  let ParserMatchClass = FPImmOperand;
1483  let PrintMethod = "printFPImmOperand";
1484}
1485
1486def fpimm8 : Operand<i32> {
1487  let ParserMatchClass = FPImmOperand;
1488  let PrintMethod = "printFPImmOperand";
1489}
1490
1491def fpimm0 : FPImmLeaf<fAny, [{
1492  return Imm.isExactlyValue(+0.0);
1493}]>;
1494
1495def fpimm_minus0 : FPImmLeaf<fAny, [{
1496  return Imm.isExactlyValue(-0.0);
1497}]>;
1498
1499def fpimm_half : FPImmLeaf<fAny, [{
1500  return Imm.isExactlyValue(+0.5);
1501}]>;
1502
1503def fpimm_one : FPImmLeaf<fAny, [{
1504  return Imm.isExactlyValue(+1.0);
1505}]>;
1506
1507def fpimm_two : FPImmLeaf<fAny, [{
1508  return Imm.isExactlyValue(+2.0);
1509}]>;
1510
1511def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1512  GISDNodeXFormEquiv<fpimm16XForm>;
1513def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1514  GISDNodeXFormEquiv<fpimm32XForm>;
1515def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1516  GISDNodeXFormEquiv<fpimm64XForm>;
1517def gi_fpimm32SIMDModImmType4 :
1518    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1519  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1520
1521// Vector lane operands
1522class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1523  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1524  let DiagnosticType = "Invalid" # Name;
1525  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1526  let RenderMethod = "addVectorIndexOperands";
1527}
1528
1529class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1530    : Operand<ty> {
1531  let ParserMatchClass = mc;
1532  let PrintMethod = "printVectorIndex";
1533}
1534
1535multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1536  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1537  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1538}
1539
1540def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1541def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1542def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1543def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1544def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1545def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1546
1547let OperandNamespace = "AArch64" in {
1548  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1549    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1550                                [{ return ((uint64_t)Imm) == 0; }]>;
1551    defm VectorIndex032b : VectorIndex<i32, VectorIndex0Operand,
1552                                [{ return ((uint32_t)Imm) == 0; }]>;
1553  }
1554}
1555defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1556                                [{ return ((uint64_t)Imm) == 1; }]>;
1557defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1558                                [{ return ((uint64_t)Imm) < 16; }]>;
1559defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1560                                [{ return ((uint64_t)Imm) < 8; }]>;
1561defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1562                                [{ return ((uint64_t)Imm) < 4; }]>;
1563defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1564                                [{ return ((uint64_t)Imm) < 2; }]>;
1565
1566defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1567                                   [{ return ((uint64_t)Imm) == 1; }]>;
1568defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1569                                   [{ return ((uint64_t)Imm) < 16; }]>;
1570defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1571                                   [{ return ((uint64_t)Imm) < 8; }]>;
1572defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1573                                   [{ return ((uint64_t)Imm) < 4; }]>;
1574defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1575                                   [{ return ((uint64_t)Imm) < 2; }]>;
1576
1577def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1578def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1579def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1580def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1581def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1582
1583defm sve_elm_idx_extdup_b
1584  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1585                [{ return ((uint64_t)Imm) < 64; }]>;
1586defm sve_elm_idx_extdup_h
1587  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1588                [{ return ((uint64_t)Imm) < 32; }]>;
1589defm sve_elm_idx_extdup_s
1590  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1591                [{ return ((uint64_t)Imm) < 16; }]>;
1592defm sve_elm_idx_extdup_d
1593  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1594                [{ return ((uint64_t)Imm) < 8; }]>;
1595defm sve_elm_idx_extdup_q
1596  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1597                [{ return ((uint64_t)Imm) < 4; }]>;
1598
1599def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
1600  return ((uint32_t)Imm) == 0;
1601}]> {
1602  let ParserMatchClass = Imm0_0Operand;
1603  let PrintMethod = "printMatrixIndex";
1604  let OperandNamespace = "AArch64";
1605  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1606}
1607def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
1608  return ((uint32_t)Imm) <= 1;
1609}]> {
1610  let ParserMatchClass = Imm0_1Operand;
1611  let PrintMethod = "printMatrixIndex";
1612}
1613def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
1614  return ((uint32_t)Imm) <= 3;
1615}]> {
1616  let ParserMatchClass = Imm0_3Operand;
1617  let PrintMethod = "printMatrixIndex";
1618}
1619def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
1620  return ((uint32_t)Imm) <= 7;
1621}]> {
1622  let ParserMatchClass = Imm0_7Operand;
1623  let PrintMethod = "printMatrixIndex";
1624}
1625def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
1626  return ((uint32_t)Imm) <= 15;
1627}]> {
1628  let ParserMatchClass = Imm0_15Operand;
1629  let PrintMethod = "printMatrixIndex";
1630}
1631
1632// SME2 vector select offset operands
1633
1634// uimm3s8 predicate
1635// True if the immediate is a multiple of 8 in the range [0,56].
1636def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
1637
1638def uimm3s8 : Operand<i64>, ImmLeaf<i64,
1639[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
1640  let PrintMethod = "printMatrixIndex<8>";
1641  let ParserMatchClass = UImm3s8Operand;
1642}
1643
1644class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
1645  let Name = "UImm" # Width # "s" # Scale # "Range";
1646  let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;
1647  let RenderMethod = "addImmScaledRangeOperands<" # Scale # ">";
1648  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ", " # OffsetVal # ", /*IsRange=*/true>";
1649  let ParserMethod = "tryParseImmRange";
1650}
1651
1652// Implicit immediate ranges 0:1 and 0:3, scale has no meaning
1653// since the immediate is zero
1654def UImm0s2RangeOperand : UImmScaledMemoryIndexedRange<0, 2, 1>;
1655def UImm0s4RangeOperand : UImmScaledMemoryIndexedRange<0, 4, 3>;
1656
1657def UImm1s2RangeOperand : UImmScaledMemoryIndexedRange<1, 2, 1>;
1658def UImm1s4RangeOperand : UImmScaledMemoryIndexedRange<1, 4, 3>;
1659def UImm2s2RangeOperand : UImmScaledMemoryIndexedRange<2, 2, 1>;
1660def UImm2s4RangeOperand : UImmScaledMemoryIndexedRange<2, 4, 3>;
1661def UImm3s2RangeOperand : UImmScaledMemoryIndexedRange<3, 2, 1>;
1662
1663def uimm0s2range : Operand<i64>, ImmLeaf<i64,
1664[{ return Imm == 0; }], UImmS1XForm> {
1665  let PrintMethod = "printImmRangeScale<2, 1>";
1666  let ParserMatchClass = UImm0s2RangeOperand;
1667  let OperandNamespace = "AArch64";
1668  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1669}
1670
1671def uimm0s4range : Operand<i64>, ImmLeaf<i64,
1672[{ return Imm == 0; }], UImmS1XForm> {
1673  let PrintMethod = "printImmRangeScale<4, 3>";
1674  let ParserMatchClass = UImm0s4RangeOperand;
1675  let OperandNamespace = "AArch64";
1676  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1677}
1678
1679def uimm1s2range : Operand<i64>, ImmLeaf<i64,
1680[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
1681  let PrintMethod = "printImmRangeScale<2, 1>";
1682  let ParserMatchClass = UImm1s2RangeOperand;
1683}
1684
1685def uimm1s4range : Operand<i64>, ImmLeaf<i64,
1686[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
1687  let PrintMethod = "printImmRangeScale<4, 3>";
1688  let ParserMatchClass = UImm1s4RangeOperand;
1689}
1690
1691def uimm2s2range : Operand<i64>, ImmLeaf<i64,
1692[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
1693  let PrintMethod = "printImmRangeScale<2, 1>";
1694  let ParserMatchClass = UImm2s2RangeOperand;
1695}
1696
1697def uimm2s4range : Operand<i64>, ImmLeaf<i64,
1698[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
1699  let PrintMethod = "printImmRangeScale<4, 3>";
1700  let ParserMatchClass = UImm2s4RangeOperand;
1701}
1702
1703def uimm3s2range : Operand<i64>, ImmLeaf<i64,
1704[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
1705  let PrintMethod = "printImmRangeScale<2, 1>";
1706  let ParserMatchClass = UImm3s2RangeOperand;
1707}
1708
1709
1710// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1711// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1712// are encoded as the eight bit value 'abcdefgh'.
1713def simdimmtype10 : Operand<i32>,
1714                    FPImmLeaf<f64, [{
1715      return AArch64_AM::isAdvSIMDModImmType10(
1716                 Imm.bitcastToAPInt().getZExtValue());
1717    }], SDNodeXForm<fpimm, [{
1718      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1719                                                           .bitcastToAPInt()
1720                                                           .getZExtValue());
1721      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1722    }]>> {
1723  let ParserMatchClass = SIMDImmType10Operand;
1724  let PrintMethod = "printSIMDType10Operand";
1725}
1726
1727
1728//---
1729// System management
1730//---
1731
1732// Base encoding for system instruction operands.
1733let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1734class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1735                  list<dag> pattern = []>
1736    : I<oops, iops, asm, operands, "", pattern> {
1737  let Inst{31-22} = 0b1101010100;
1738  let Inst{21}    = L;
1739}
1740
1741// System instructions which do not have an Rt register.
1742class SimpleSystemI<bit L, dag iops, string asm, string operands,
1743                    list<dag> pattern = []>
1744    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1745  let Inst{4-0} = 0b11111;
1746}
1747
1748// System instructions which have an Rt register.
1749class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1750                list<dag> pattern = []>
1751    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1752      Sched<[WriteSys]> {
1753  bits<5> Rt;
1754  let Inst{4-0} = Rt;
1755}
1756
1757// System instructions for transactional memory extension
1758class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1759                    string asm, string operands, list<dag> pattern>
1760    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1761      Sched<[WriteSys]> {
1762  let Inst{20-12} = 0b000110011;
1763  let Inst{11-8} = CRm;
1764  let Inst{7-5} = op2;
1765  let DecoderMethod = "";
1766
1767  let mayLoad = 1;
1768  let mayStore = 1;
1769}
1770
1771// System instructions for transactional memory - single input operand
1772class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1773    : TMBaseSystemI<0b1, CRm, 0b011,
1774                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1775  bits<5> Rt;
1776  let Inst{4-0} = Rt;
1777}
1778
1779// System instructions that pass a register argument
1780// This class assumes the register is for input rather than output.
1781class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1782                      list<dag> pattern = []>
1783    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1784  let Inst{20-12} = 0b000110001;
1785  let Inst{11-8} = CRm;
1786  let Inst{7-5} = Op2;
1787}
1788
1789// System instructions for transactional memory - no operand
1790class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1791    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1792  let Inst{4-0} = 0b11111;
1793}
1794
1795// System instructions for exit from transactions
1796class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1797    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1798      Sched<[WriteSys]> {
1799  bits<16> imm;
1800  let Inst{31-24} = 0b11010100;
1801  let Inst{23-21} = op1;
1802  let Inst{20-5}  = imm;
1803  let Inst{4-0}   = 0b00000;
1804}
1805
1806class APASI : SimpleSystemI<0, (ins GPR64:$Xt), "apas", "\t$Xt">, Sched<[]> {
1807  bits<5> Xt;
1808  let Inst{20-5} = 0b0111001110000000;
1809  let Inst{4-0} = Xt;
1810  let DecoderNamespace = "APAS";
1811}
1812
1813// Hint instructions that take both a CRm and a 3-bit immediate.
1814// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1815// model patterns with sufficiently fine granularity
1816let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1817  class HintI<string mnemonic>
1818      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1819                      [(int_aarch64_hint imm0_127:$imm)]>,
1820        Sched<[WriteHint]> {
1821    bits <7> imm;
1822    let Inst{20-12} = 0b000110010;
1823    let Inst{11-5} = imm;
1824  }
1825
1826def PHintInstOperand : AsmOperandClass {
1827    let Name = "PHint";
1828    let ParserMethod = "tryParsePHintInstOperand";
1829}
1830
1831def phint_op : Operand<i32> {
1832    let ParserMatchClass = PHintInstOperand;
1833   let PrintMethod = "printPHintOp";
1834}
1835
1836class STSHHI
1837    : SimpleSystemI<0, (ins phint_op:$policy), "stshh", "\t$policy", []>,
1838      Sched<[WriteHint]> {
1839  bits<3> policy;
1840  let Inst{20-12} = 0b000011001;
1841  let Inst{11-8} = 0b0110;
1842  let Inst{7-5} = policy;
1843}
1844
1845// System instructions taking a single literal operand which encodes into
1846// CRm. op2 differentiates the opcodes.
1847def BarrierAsmOperand : AsmOperandClass {
1848  let Name = "Barrier";
1849  let ParserMethod = "tryParseBarrierOperand";
1850}
1851def barrier_op : Operand<i32> {
1852  let PrintMethod = "printBarrierOption";
1853  let ParserMatchClass = BarrierAsmOperand;
1854}
1855def BarriernXSAsmOperand : AsmOperandClass {
1856  let Name = "BarriernXS";
1857  let ParserMethod = "tryParseBarriernXSOperand";
1858}
1859def barrier_nxs_op : Operand<i32> {
1860  let PrintMethod = "printBarriernXSOption";
1861  let ParserMatchClass = BarriernXSAsmOperand;
1862}
1863class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1864                 list<dag> pattern = []>
1865    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1866      Sched<[WriteBarrier]> {
1867  bits<4> CRm;
1868  let Inst{20-12} = 0b000110011;
1869  let Inst{11-8} = CRm;
1870  let Inst{7-5} = opc;
1871}
1872
1873class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1874    : SimpleSystemI<0, (ins), asm, "", pattern>,
1875      Sched<[WriteHint]> {
1876  bits<4> CRm;
1877  let CRm = 0b0011;
1878  let Inst{31-12} = 0b11010101000000110010;
1879  let Inst{11-8} = CRm;
1880  let Inst{7-5} = op2;
1881  let Inst{4-0} = 0b11111;
1882}
1883
1884// MRS/MSR system instructions. These have different operand classes because
1885// a different subset of registers can be accessed through each instruction.
1886def MRSSystemRegisterOperand : AsmOperandClass {
1887  let Name = "MRSSystemRegister";
1888  let ParserMethod = "tryParseSysReg";
1889  let DiagnosticType = "MRS";
1890}
1891// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1892def mrs_sysreg_op : Operand<i32> {
1893  let ParserMatchClass = MRSSystemRegisterOperand;
1894  let DecoderMethod = "DecodeMRSSystemRegister";
1895  let PrintMethod = "printMRSSystemRegister";
1896}
1897
1898def MSRSystemRegisterOperand : AsmOperandClass {
1899  let Name = "MSRSystemRegister";
1900  let ParserMethod = "tryParseSysReg";
1901  let DiagnosticType = "MSR";
1902}
1903def msr_sysreg_op : Operand<i32> {
1904  let ParserMatchClass = MSRSystemRegisterOperand;
1905  let DecoderMethod = "DecodeMSRSystemRegister";
1906  let PrintMethod = "printMSRSystemRegister";
1907}
1908
1909def PSBHintOperand : AsmOperandClass {
1910  let Name = "PSBHint";
1911  let ParserMethod = "tryParsePSBHint";
1912}
1913def psbhint_op : Operand<i32> {
1914  let ParserMatchClass = PSBHintOperand;
1915  let PrintMethod = "printPSBHintOp";
1916  let MCOperandPredicate = [{
1917    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1918    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1919    if (!MCOp.isImm())
1920      return false;
1921    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1922  }];
1923}
1924
1925def BTIHintOperand : AsmOperandClass {
1926  let Name = "BTIHint";
1927  let ParserMethod = "tryParseBTIHint";
1928}
1929def btihint_op : Operand<i32> {
1930  let ParserMatchClass = BTIHintOperand;
1931  let PrintMethod = "printBTIHintOp";
1932  let MCOperandPredicate = [{
1933    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1934    if (!MCOp.isImm())
1935      return false;
1936    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1937  }];
1938}
1939
1940class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1941                       "mrs", "\t$Rt, $systemreg"> {
1942  bits<16> systemreg;
1943  let Inst{20-5} = systemreg;
1944  let DecoderNamespace = "Fallback";
1945  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1946  // require doing this. The alternative was to explicitly model each one, but
1947  // it feels like it is unnecessary because it seems there are no negative
1948  // consequences setting these flags for all.
1949  let Defs = [NZCV];
1950}
1951
1952// FIXME: Some of these def NZCV, others don't. Best way to model that?
1953// Explicitly modeling each of the system register as a register class
1954// would do it, but feels like overkill at this point.
1955class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1956                       "msr", "\t$systemreg, $Rt"> {
1957  bits<16> systemreg;
1958  let Inst{20-5} = systemreg;
1959  let DecoderNamespace = "Fallback";
1960}
1961
1962def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1963  let Name = "SystemPStateFieldWithImm0_15";
1964  let ParserMethod = "tryParseSysReg";
1965}
1966def pstatefield4_op : Operand<i32> {
1967  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1968  let PrintMethod = "printSystemPStateField";
1969  let MCOperandPredicate = [{
1970    if (!MCOp.isImm())
1971      return false;
1972    return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
1973  }];
1974}
1975
1976// Instructions to modify PSTATE, no input reg
1977let Defs = [NZCV] in
1978class PstateWriteSimple<dag iops, string asm, string operands>
1979  : SimpleSystemI<0, iops, asm, operands> {
1980
1981  let Inst{20-19} = 0b00;
1982  let Inst{15-12} = 0b0100;
1983}
1984
1985class MSRpstateImm0_15
1986  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1987                  "\t$pstatefield, $imm">,
1988    Sched<[WriteSys]> {
1989
1990  bits<6> pstatefield;
1991  bits<4> imm;
1992  let Inst{18-16} = pstatefield{5-3};
1993  let Inst{11-8} = imm;
1994  let Inst{7-5} = pstatefield{2-0};
1995
1996  let DecoderMethod = "DecodeSystemPStateImm0_15Instruction";
1997  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1998  // Fail the decoder should attempt to decode the instruction as MSRI.
1999  let hasCompleteDecoder = false;
2000}
2001
2002def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
2003  let Name = "SystemPStateFieldWithImm0_1";
2004  let ParserMethod = "tryParseSysReg";
2005}
2006def pstatefield1_op : Operand<i32> {
2007  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
2008  let PrintMethod = "printSystemPStateField";
2009  let MCOperandPredicate = [{
2010    if (!MCOp.isImm())
2011      return false;
2012    return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
2013  }];
2014}
2015
2016class MSRpstateImm0_1
2017  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
2018                 "\t$pstatefield, $imm">,
2019    Sched<[WriteSys]> {
2020
2021  bits<9> pstatefield;
2022  bit imm;
2023  let Inst{18-16} = pstatefield{5-3};
2024  let Inst{11-9} = pstatefield{8-6};
2025  let Inst{8} = imm;
2026  let Inst{7-5} = pstatefield{2-0};
2027
2028  let DecoderMethod = "DecodeSystemPStateImm0_1Instruction";
2029  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
2030  // Fail the decoder should attempt to decode the instruction as MSRI.
2031  let hasCompleteDecoder = false;
2032  let DecoderNamespace = "Fallback";
2033}
2034
2035// SYS and SYSL generic system instructions.
2036def SysCRAsmOperand : AsmOperandClass {
2037  let Name = "SysCR";
2038  let ParserMethod = "tryParseSysCROperand";
2039}
2040
2041def sys_cr_op : Operand<i32> {
2042  let PrintMethod = "printSysCROperand";
2043  let ParserMatchClass = SysCRAsmOperand;
2044}
2045
2046class SystemXtI<bit L, string asm>
2047  : RtSystemI<L, (outs),
2048       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
2049       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
2050  bits<3> op1;
2051  bits<4> Cn;
2052  bits<4> Cm;
2053  bits<3> op2;
2054  let Inst{20-19} = 0b01;
2055  let Inst{18-16} = op1;
2056  let Inst{15-12} = Cn;
2057  let Inst{11-8}  = Cm;
2058  let Inst{7-5}   = op2;
2059}
2060
2061class SystemLXtI<bit L, string asm>
2062  : RtSystemI<L, (outs),
2063       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
2064       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
2065  bits<3> op1;
2066  bits<4> Cn;
2067  bits<4> Cm;
2068  bits<3> op2;
2069  let Inst{20-19} = 0b01;
2070  let Inst{18-16} = op1;
2071  let Inst{15-12} = Cn;
2072  let Inst{11-8}  = Cm;
2073  let Inst{7-5}   = op2;
2074}
2075
2076def RangePrefetchOperand : AsmOperandClass {
2077  let Name = "RangePrefetch";
2078  let ParserMethod = "tryParseRPRFMOperand";
2079  let PredicateMethod = "isPrefetch";
2080  let RenderMethod = "addPrefetchOperands";
2081}
2082
2083def rprfop : Operand<i32>, TImmLeaf<i32, [{
2084    return (((uint32_t)Imm) <= 63);
2085  }]> {
2086  let PrintMethod = "printRPRFMOperand";
2087  let ParserMatchClass = RangePrefetchOperand;
2088}
2089
2090// Branch (register) instructions:
2091//
2092//  case opc of
2093//    0001 blr
2094//    0000 br
2095//    0101 dret
2096//    0100 eret
2097//    0010 ret
2098//    otherwise UNDEFINED
2099class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
2100                    string operands, list<dag> pattern>
2101    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
2102  let Inst{31-25} = 0b1101011;
2103  let Inst{24-21} = opc;
2104  let Inst{20-16} = 0b11111;
2105  let Inst{15-10} = 0b000000;
2106  let Inst{4-0}   = 0b00000;
2107}
2108
2109class BranchReg<bits<4> opc, string asm, list<dag> pattern>
2110    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
2111  bits<5> Rn;
2112  let Inst{9-5} = Rn;
2113}
2114
2115let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
2116class SpecialReturn<bits<4> opc, string asm>
2117    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
2118  let Inst{9-5} = 0b11111;
2119}
2120
2121let mayLoad = 1 in
2122class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
2123  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
2124  Sched<[]> {
2125  bits<5> Rn;
2126  bits<5> Rt;
2127  let Inst{31-30} = sz;
2128  let Inst{29-10} = 0b11100010111111110000;
2129  let Inst{9-5} = Rn;
2130  let Inst{4-0} = Rt;
2131}
2132
2133class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
2134               list<dag> pattern>
2135  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
2136  let isAuthenticated = 1;
2137  let Inst{31-25} = 0b1101011;
2138  let Inst{20-11} = 0b1111100001;
2139  let Inst{10} = M;
2140  let Inst{4-0} = 0b11111;
2141}
2142
2143class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
2144  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
2145  bits<5> Rn;
2146  bits<5> Rm;
2147  let Inst{24-22} = 0b100;
2148  let Inst{21} = op;
2149  let Inst{9-5} = Rn;
2150  let Inst{4-0} = Rm;
2151}
2152
2153class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
2154  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
2155  bits<5> Rn;
2156  let Inst{24} = 0;
2157  let Inst{23-21} = opc;
2158  let Inst{9-5} = Rn;
2159}
2160
2161let Uses = [LR,SP] in
2162class AuthReturn<bits<3> op, bits<1> M, string asm>
2163  : AuthBase<M, (outs), (ins), asm, "", []> {
2164  let Inst{24} = 0;
2165  let Inst{23-21} = op;
2166  let Inst{9-0} = 0b1111111111;
2167}
2168
2169let mayLoad = 1 in
2170class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
2171                   string operands, string cstr>
2172  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
2173  bits<10> offset;
2174  bits<5> Rn;
2175  bits<5> Rt;
2176  let isAuthenticated = 1;
2177  let Inst{31-24} = 0b11111000;
2178  let Inst{23} = M;
2179  let Inst{22} = offset{9};
2180  let Inst{21} = 1;
2181  let Inst{20-12} = offset{8-0};
2182  let Inst{11} = W;
2183  let Inst{10} = 1;
2184  let Inst{9-5} = Rn;
2185  let Inst{4-0} = Rt;
2186
2187  let DecoderMethod = "DecodeAuthLoadInstruction";
2188}
2189
2190multiclass AuthLoad<bit M, string asm, Operand opr> {
2191  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
2192                               (ins GPR64sp:$Rn, opr:$offset),
2193                               asm, "\t$Rt, [$Rn, $offset]", "">;
2194  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
2195                               (ins GPR64sp:$Rn, opr:$offset),
2196                               asm, "\t$Rt, [$Rn, $offset]!",
2197                               "$Rn = $wback,@earlyclobber $wback">;
2198
2199  def : InstAlias<asm # "\t$Rt, [$Rn]",
2200                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
2201
2202  def : InstAlias<asm # "\t$Rt, [$wback]!",
2203                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
2204}
2205
2206//---
2207// Conditional branch instruction.
2208//---
2209
2210// Condition code.
2211// 4-bit immediate. Pretty-printed as <cc>
2212def ccode : Operand<i32> {
2213  let PrintMethod = "printCondCode";
2214  let ParserMatchClass = CondCode;
2215}
2216def inv_ccode : Operand<i32> {
2217  // AL and NV are invalid in the aliases which use inv_ccode
2218  let PrintMethod = "printInverseCondCode";
2219  let ParserMatchClass = CondCode;
2220  let MCOperandPredicate = [{
2221    return MCOp.isImm() &&
2222           MCOp.getImm() != AArch64CC::AL &&
2223           MCOp.getImm() != AArch64CC::NV;
2224  }];
2225}
2226
2227// Conditional branch target. 19-bit immediate. The low two bits of the target
2228// offset are implied zero and so are not part of the immediate.
2229def am_brcond : Operand<OtherVT> {
2230  let EncoderMethod = "getCondBranchTargetOpValue";
2231  let DecoderMethod = "DecodePCRelLabel19";
2232  let PrintMethod = "printAlignedLabel";
2233  let ParserMatchClass = PCRelLabel19Operand;
2234  let OperandType = "OPERAND_PCREL";
2235}
2236
2237// Conditional branch target. 9-bit immediate. The low two bits of the target
2238// offset are implied zero and so are not part of the immediate.
2239def am_brcmpcond : Operand<OtherVT> {
2240  let EncoderMethod = "getCondCompBranchTargetOpValue";
2241  let DecoderMethod = "DecodePCRelLabel9";
2242  let PrintMethod   = "printAlignedLabel";
2243  let ParserMatchClass = PCRelLabel9Operand;
2244  let OperandType = "OPERAND_PCREL";
2245}
2246
2247
2248class BranchCond<bit bit4, string mnemonic>
2249   : I<(outs), (ins ccode:$cond, am_brcond:$target),
2250       mnemonic, ".$cond\t$target", "",
2251       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
2252  let isBranch = 1;
2253  let isTerminator = 1;
2254  let Uses = [NZCV];
2255
2256  bits<4> cond;
2257  bits<19> target;
2258  let Inst{31-24} = 0b01010100;
2259  let Inst{23-5} = target;
2260  let Inst{4} = bit4;
2261  let Inst{3-0} = cond;
2262}
2263
2264//---
2265// Compare-and-branch instructions.
2266//---
2267class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
2268    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
2269         asm, "\t$Rt, $target", "",
2270         [(node regtype:$Rt, bb:$target)]>,
2271      Sched<[WriteBr]> {
2272  let isBranch = 1;
2273  let isTerminator = 1;
2274
2275  bits<5> Rt;
2276  bits<19> target;
2277  let Inst{30-25} = 0b011010;
2278  let Inst{24}    = op;
2279  let Inst{23-5}  = target;
2280  let Inst{4-0}   = Rt;
2281}
2282
2283multiclass CmpBranch<bit op, string asm, SDNode node> {
2284  def W : BaseCmpBranch<GPR32, op, asm, node> {
2285    let Inst{31} = 0;
2286  }
2287  def X : BaseCmpBranch<GPR64, op, asm, node> {
2288    let Inst{31} = 1;
2289  }
2290}
2291
2292//---
2293// Test-bit-and-branch instructions.
2294//---
2295// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
2296// the target offset are implied zero and so are not part of the immediate.
2297def am_tbrcond : Operand<OtherVT> {
2298  let EncoderMethod = "getTestBranchTargetOpValue";
2299  let PrintMethod = "printAlignedLabel";
2300  let ParserMatchClass = BranchTarget14Operand;
2301  let OperandType = "OPERAND_PCREL";
2302}
2303
2304// AsmOperand classes to emit (or not) special diagnostics
2305def TBZImm0_31Operand : AsmOperandClass {
2306  let Name = "TBZImm0_31";
2307  let PredicateMethod = "isImmInRange<0,31>";
2308  let RenderMethod = "addImmOperands";
2309}
2310def TBZImm32_63Operand : AsmOperandClass {
2311  let Name = "Imm32_63";
2312  let PredicateMethod = "isImmInRange<32,63>";
2313  let DiagnosticType = "InvalidImm0_63";
2314  let RenderMethod = "addImmOperands";
2315}
2316
2317class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
2318  return (((uint32_t)Imm) < 32);
2319}]> {
2320  let ParserMatchClass = matcher;
2321}
2322
2323def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
2324def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
2325
2326def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
2327  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
2328}]> {
2329  let ParserMatchClass = TBZImm32_63Operand;
2330}
2331
2332class BaseTestBranch<RegisterClass regtype, Operand immtype,
2333                     bit op, string asm, SDNode node>
2334    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
2335       asm, "\t$Rt, $bit_off, $target", "",
2336       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
2337      Sched<[WriteBr]> {
2338  let isBranch = 1;
2339  let isTerminator = 1;
2340
2341  bits<5> Rt;
2342  bits<6> bit_off;
2343  bits<14> target;
2344
2345  let Inst{30-25} = 0b011011;
2346  let Inst{24}    = op;
2347  let Inst{23-19} = bit_off{4-0};
2348  let Inst{18-5}  = target;
2349  let Inst{4-0}   = Rt;
2350
2351  let DecoderMethod = "DecodeTestAndBranch";
2352}
2353
2354multiclass TestBranch<bit op, string asm, SDNode node> {
2355  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
2356    let Inst{31} = 0;
2357  }
2358
2359  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
2360    let Inst{31} = 1;
2361  }
2362
2363  // Alias X-reg with 0-31 imm to W-Reg.
2364  def : InstAlias<asm # "\t$Rd, $imm, $target",
2365                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
2366                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
2367  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
2368            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
2369            tbz_imm0_31_diag:$imm, bb:$target)>;
2370}
2371
2372//---
2373// Unconditional branch (immediate) instructions.
2374//---
2375def am_b_target : Operand<OtherVT> {
2376  let EncoderMethod = "getBranchTargetOpValue";
2377  let PrintMethod = "printAlignedLabel";
2378  let ParserMatchClass = BranchTarget26Operand;
2379  let OperandType = "OPERAND_PCREL";
2380}
2381def am_bl_target : Operand<i64> {
2382  let EncoderMethod = "getBranchTargetOpValue";
2383  let PrintMethod = "printAlignedLabel";
2384  let ParserMatchClass = BranchTarget26Operand;
2385  let OperandType = "OPERAND_PCREL";
2386}
2387
2388class BImm<bit op, dag iops, string asm, list<dag> pattern>
2389    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
2390  bits<26> addr;
2391  let Inst{31}    = op;
2392  let Inst{30-26} = 0b00101;
2393  let Inst{25-0}  = addr;
2394
2395  let DecoderMethod = "DecodeUnconditionalBranch";
2396}
2397
2398class BranchImm<bit op, string asm, list<dag> pattern>
2399    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2400class CallImm<bit op, string asm, list<dag> pattern>
2401    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2402
2403//---
2404// Basic one-operand data processing instructions.
2405//---
2406
2407let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2408class BaseOneOperandData<bit sf, bit S, bits<5> opc2, bits<6> opc,
2409                         RegisterClass regtype, string asm,
2410                         SDPatternOperator node>
2411  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2412      [(set regtype:$Rd, (node regtype:$Rn))]>,
2413    Sched<[WriteI, ReadI]> {
2414  bits<5> Rd;
2415  bits<5> Rn;
2416
2417  let Inst{31} = sf;
2418  let Inst{30} = 0b1;
2419  let Inst{29} = S;
2420  let Inst{28-21} = 0b11010110;
2421  let Inst{20-16} = opc2;
2422  let Inst{15-10} = opc;
2423  let Inst{9-5}   = Rn;
2424  let Inst{4-0}   = Rd;
2425}
2426
2427let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2428multiclass OneOperandData<bits<6> opc, string asm,
2429                          SDPatternOperator node = null_frag> {
2430  def Wr : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2431
2432  def Xr : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2433}
2434
2435class OneWRegData<bits<6> opc, string asm, SDPatternOperator node>
2436    : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2437
2438class OneXRegData<bits<6> opc, string asm, SDPatternOperator node>
2439    : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2440
2441class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2442                      SDPatternOperator op>
2443  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2444      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2445    Sched<[WriteI, ReadI]> {
2446  bits<5> Rd;
2447  bits<5> Rn;
2448  let Inst{31-15} = 0b11011010110000010;
2449  let Inst{14-12} = opcode_prefix;
2450  let Inst{11-10} = opcode;
2451  let Inst{9-5} = Rn;
2452  let Inst{4-0} = Rd;
2453}
2454
2455class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2456                   SDPatternOperator op>
2457  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2458      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2459    Sched<[]> {
2460  bits<5> Rd;
2461  let Inst{31-15} = 0b11011010110000010;
2462  let Inst{14-12} = opcode_prefix;
2463  let Inst{11-10} = opcode;
2464  let Inst{9-5} = 0b11111;
2465  let Inst{4-0} = Rd;
2466}
2467
2468class SignAuthTwoOperand<bits<4> opc, string asm,
2469                         SDPatternOperator OpNode>
2470  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2471      asm, "\t$Rd, $Rn, $Rm", "",
2472      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2473    Sched<[WriteI, ReadI, ReadI]> {
2474  bits<5> Rd;
2475  bits<5> Rn;
2476  bits<5> Rm;
2477  let Inst{31-21} = 0b10011010110;
2478  let Inst{20-16} = Rm;
2479  let Inst{15-14} = 0b00;
2480  let Inst{13-10} = opc;
2481  let Inst{9-5}   = Rn;
2482  let Inst{4-0}   = Rd;
2483}
2484
2485class ClearAuth<bits<1> data, string asm>
2486  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2487  bits<5> Rd;
2488  let Inst{31-11} = 0b110110101100000101000;
2489  let Inst{10} = data;
2490  let Inst{9-5} = 0b11111;
2491  let Inst{4-0} = Rd;
2492}
2493
2494// v9.5-A FEAT_PAuth_LR
2495
2496class SignAuthFixedRegs<bits<5> opcode2, bits<6> opcode, string asm>
2497  : I<(outs), (ins), asm, "", "", []>,
2498    Sched<[WriteI, ReadI]> {
2499  let Inst{31} = 0b1; // sf
2500  let Inst{30} = 0b1;
2501  let Inst{29} = 0b0; // S
2502  let Inst{28-21} = 0b11010110;
2503  let Inst{20-16} = opcode2;
2504  let Inst{15-10} = opcode;
2505  let Inst{9-5} = 0b11111; // Rn
2506  let Inst{4-0} = 0b11110; // Rd
2507}
2508
2509def PAuthPCRelLabel16Operand : PCRelLabel<16> {
2510  let Name = "PAuthPCRelLabel16";
2511  let PredicateMethod = "isPAuthPCRelLabel16Operand";
2512}
2513def am_pauth_pcrel : Operand<OtherVT> {
2514  let EncoderMethod = "getPAuthPCRelOpValue";
2515  let DecoderMethod = "DecodePCRelLabel16";
2516  let PrintMethod = "printAlignedLabel";
2517  let ParserMatchClass = PAuthPCRelLabel16Operand;
2518  let OperandType = "OPERAND_PCREL";
2519}
2520
2521class SignAuthPCRel<bits<2> opc, string asm>
2522  : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2523    Sched<[]> {
2524  bits<16> label;
2525  let Inst{31} = 0b1; // sf
2526  let Inst{30-23} = 0b11100111;
2527  let Inst{22-21} = opc;
2528  let Inst{20-5} = label; // imm
2529  let Inst{4-0} = 0b11111; // Rd
2530}
2531
2532class SignAuthOneReg<bits<5> opcode2, bits<6> opcode, string asm>
2533  : I<(outs), (ins GPR64:$Rn), asm, "\t$Rn", "", []>,
2534    Sched<[]> {
2535  bits<5> Rn;
2536  let Inst{31} = 0b1; // sf
2537  let Inst{30} = 0b1;
2538  let Inst{29} = 0b0; // S
2539  let Inst{28-21} = 0b11010110;
2540  let Inst{20-16} = opcode2;
2541  let Inst{15-10} = opcode;
2542  let Inst{9-5} = Rn;
2543  let Inst{4-0} = 0b11110; // Rd
2544}
2545
2546class SignAuthReturnPCRel<bits<3> opc, bits<5> op2, string asm>
2547  : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2548    Sched<[WriteAtomic]> {
2549  bits<16> label;
2550  let Inst{31-24} = 0b01010101;
2551  let Inst{23-21} = opc;
2552  let Inst{20-5} = label; // imm16
2553  let Inst{4-0} = op2;
2554}
2555
2556class SignAuthReturnReg<bits<6> op3, string asm>
2557  : I<(outs), (ins GPR64common:$Rm), asm, "\t$Rm", "", []>,
2558    Sched<[WriteAtomic]> {
2559  bits<5> Rm;
2560  let Inst{31-25} = 0b1101011;
2561  let Inst{24-21} = 0b0010; // opc
2562  let Inst{20-16} = 0b11111; // op2
2563  let Inst{15-10} = op3;
2564  let Inst{9-5} = 0b11111; // Rn
2565  let Inst{4-0} = Rm; // op4 (Rm)
2566}
2567
2568// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2569class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2570    : I<(outs), iops, asm, ops, "", []>,
2571      Sched<[WriteI, ReadI, ReadI]> {
2572  let Uses = [NZCV];
2573  let Defs = [NZCV];
2574  bits<5> Rn;
2575  let Inst{31}    = sf;
2576  let Inst{30-15} = 0b0111010000000000;
2577  let Inst{14}    = sz;
2578  let Inst{13-10} = 0b0010;
2579  let Inst{9-5}   = Rn;
2580  let Inst{4-0}   = 0b01101;
2581}
2582
2583class FlagRotate<dag iops, string asm, string ops>
2584    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2585  bits<6> imm;
2586  bits<4> mask;
2587  let Inst{20-15} = imm;
2588  let Inst{13-10} = 0b0001;
2589  let Inst{4}     = 0b0;
2590  let Inst{3-0}   = mask;
2591}
2592
2593//---
2594// Basic two-operand data processing instructions.
2595//---
2596class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2597                          list<dag> pattern>
2598    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2599        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2600      Sched<[WriteI, ReadI, ReadI]> {
2601  let Uses = [NZCV];
2602  bits<5> Rd;
2603  bits<5> Rn;
2604  bits<5> Rm;
2605  let Inst{30}    = isSub;
2606  let Inst{28-21} = 0b11010000;
2607  let Inst{20-16} = Rm;
2608  let Inst{15-10} = 0;
2609  let Inst{9-5}   = Rn;
2610  let Inst{4-0}   = Rd;
2611}
2612
2613class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2614                      SDNode OpNode>
2615    : BaseBaseAddSubCarry<isSub, regtype, asm,
2616        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2617
2618class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2619                              SDNode OpNode>
2620    : BaseBaseAddSubCarry<isSub, regtype, asm,
2621        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]> {
2622  let Defs = [NZCV];
2623}
2624
2625multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2626                       SDNode OpNode, SDNode OpNode_setflags> {
2627  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2628    let Inst{31} = 0;
2629    let Inst{29} = 0;
2630  }
2631  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2632    let Inst{31} = 1;
2633    let Inst{29} = 0;
2634  }
2635
2636  // Sets flags.
2637  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2638                                    OpNode_setflags> {
2639    let Inst{31} = 0;
2640    let Inst{29} = 1;
2641  }
2642  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2643                                    OpNode_setflags> {
2644    let Inst{31} = 1;
2645    let Inst{29} = 1;
2646  }
2647}
2648
2649class BaseTwoOperandRegReg<bit sf, bit S, bits<6> opc, RegisterClass regtype,
2650                           string asm, SDPatternOperator OpNode,
2651                           RegisterClass in1regtype = regtype,
2652                           RegisterClass in2regtype = regtype>
2653  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2654      asm, "\t$Rd, $Rn, $Rm", "",
2655      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2656  bits<5> Rd;
2657  bits<5> Rn;
2658  bits<5> Rm;
2659  let Inst{31}    = sf;
2660  let Inst{30}    = 0b0;
2661  let Inst{29}    = S;
2662  let Inst{28-21} = 0b11010110;
2663  let Inst{20-16} = Rm;
2664  let Inst{15-10} = opc;
2665  let Inst{9-5}   = Rn;
2666  let Inst{4-0}   = Rd;
2667}
2668
2669class BaseDiv<bit size, bit isSigned, RegisterClass regtype, string asm,
2670              SDPatternOperator OpNode>
2671    : BaseTwoOperandRegReg<size, 0b0, {0,0,0,0,1,?}, regtype, asm, OpNode> {
2672  let Inst{10}    = isSigned;
2673}
2674
2675multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2676  def Wr : BaseDiv<0b0, isSigned, GPR32, asm, OpNode>,
2677           Sched<[WriteID32, ReadID, ReadID]>;
2678
2679  def Xr : BaseDiv<0b1, isSigned, GPR64, asm, OpNode>,
2680           Sched<[WriteID64, ReadID, ReadID]>;
2681}
2682
2683class BaseShift<bit size, bits<2> shift_type, RegisterClass regtype, string asm,
2684                SDPatternOperator OpNode = null_frag>
2685  : BaseTwoOperandRegReg<size, 0b0, {0,0,1,0,?,?}, regtype, asm, OpNode>,
2686    Sched<[WriteIS, ReadI]> {
2687  let Inst{11-10} = shift_type;
2688}
2689
2690multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2691  def Wr : BaseShift<0b0, shift_type, GPR32, asm>;
2692
2693  def Xr : BaseShift<0b1, shift_type, GPR64, asm, OpNode>;
2694
2695  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2696            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2697                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2698
2699  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2700            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2701
2702  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2703            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2704
2705  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2706            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2707
2708  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2709            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2710                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2711
2712  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2713            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2714                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2715}
2716
2717class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2718    : InstAlias<asm#"\t$dst, $src1, $src2",
2719                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2720
2721class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2722                       RegisterClass addtype, string asm,
2723                       list<dag> pattern>
2724  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2725      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2726  bits<5> Rd;
2727  bits<5> Rn;
2728  bits<5> Rm;
2729  bits<5> Ra;
2730  let Inst{30-24} = 0b0011011;
2731  let Inst{23-21} = opc;
2732  let Inst{20-16} = Rm;
2733  let Inst{15}    = isSub;
2734  let Inst{14-10} = Ra;
2735  let Inst{9-5}   = Rn;
2736  let Inst{4-0}   = Rd;
2737}
2738
2739multiclass MulAccum<bit isSub, string asm> {
2740  // MADD/MSUB generation is decided by MachineCombiner.cpp
2741  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2742      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2743    let Inst{31} = 0;
2744  }
2745
2746  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2747      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2748    let Inst{31} = 1;
2749  }
2750}
2751
2752class WideMulAccum<bit isSub, bits<3> opc, string asm,
2753                   SDNode AccNode, SDNode ExtNode>
2754  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2755    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2756                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2757    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2758  let Inst{31} = 1;
2759}
2760
2761class MulHi<bits<3> opc, string asm, SDNode OpNode>
2762  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2763      asm, "\t$Rd, $Rn, $Rm", "",
2764      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2765    Sched<[WriteIM64, ReadIM, ReadIM]> {
2766  bits<5> Rd;
2767  bits<5> Rn;
2768  bits<5> Rm;
2769  let Inst{31-24} = 0b10011011;
2770  let Inst{23-21} = opc;
2771  let Inst{20-16} = Rm;
2772  let Inst{15}    = 0;
2773  let Inst{14-10} = 0b11111;
2774  let Unpredictable{14-10} = 0b11111;
2775  let Inst{9-5}   = Rn;
2776  let Inst{4-0}   = Rd;
2777
2778  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2779  // (i.e. all bits 1) but is ignored by the processor.
2780  let PostEncoderMethod = "fixMulHigh";
2781}
2782
2783class MulAccumWAlias<string asm, Instruction inst>
2784    : InstAlias<asm#"\t$dst, $src1, $src2",
2785                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2786class MulAccumXAlias<string asm, Instruction inst>
2787    : InstAlias<asm#"\t$dst, $src1, $src2",
2788                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2789class WideMulAccumAlias<string asm, Instruction inst>
2790    : InstAlias<asm#"\t$dst, $src1, $src2",
2791                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2792
2793class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2794              SDPatternOperator OpNode, string asm>
2795  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2796      asm, "\t$Rd, $Rn, $Rm", "",
2797      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2798    Sched<[WriteISReg, ReadI, ReadISReg]> {
2799  bits<5> Rd;
2800  bits<5> Rn;
2801  bits<5> Rm;
2802
2803  let Inst{31} = sf;
2804  let Inst{30-21} = 0b0011010110;
2805  let Inst{20-16} = Rm;
2806  let Inst{15-13} = 0b010;
2807  let Inst{12} = C;
2808  let Inst{11-10} = sz;
2809  let Inst{9-5} = Rn;
2810  let Inst{4-0} = Rd;
2811  let Predicates = [HasCRC];
2812}
2813
2814//---
2815// Address generation.
2816//---
2817
2818class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2819    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2820        pattern>,
2821      Sched<[WriteI]> {
2822  bits<5>  Xd;
2823  bits<21> label;
2824  let Inst{31}    = page;
2825  let Inst{30-29} = label{1-0};
2826  let Inst{28-24} = 0b10000;
2827  let Inst{23-5}  = label{20-2};
2828  let Inst{4-0}   = Xd;
2829
2830  let DecoderMethod = "DecodeAdrInstruction";
2831}
2832
2833//---
2834// Move immediate.
2835//---
2836
2837def movimm32_imm : Operand<i32> {
2838  let ParserMatchClass = AsmImmRange<0, 65535>;
2839  let EncoderMethod = "getMoveWideImmOpValue";
2840  let PrintMethod = "printImm";
2841}
2842def movimm32_shift : Operand<i32> {
2843  let PrintMethod = "printShifter";
2844  let ParserMatchClass = MovImm32ShifterOperand;
2845}
2846def movimm64_shift : Operand<i32> {
2847  let PrintMethod = "printShifter";
2848  let ParserMatchClass = MovImm64ShifterOperand;
2849}
2850
2851let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2852class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2853                        string asm>
2854  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2855       asm, "\t$Rd, $imm$shift", "", []>,
2856    Sched<[WriteImm]> {
2857  bits<5> Rd;
2858  bits<16> imm;
2859  bits<6> shift;
2860  let Inst{30-29} = opc;
2861  let Inst{28-23} = 0b100101;
2862  let Inst{22-21} = shift{5-4};
2863  let Inst{20-5}  = imm;
2864  let Inst{4-0}   = Rd;
2865
2866  let DecoderMethod = "DecodeMoveImmInstruction";
2867}
2868
2869multiclass MoveImmediate<bits<2> opc, string asm> {
2870  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2871    let Inst{31} = 0;
2872  }
2873
2874  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2875    let Inst{31} = 1;
2876  }
2877}
2878
2879let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2880class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2881                          string asm>
2882  : I<(outs regtype:$Rd),
2883      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2884       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2885    Sched<[WriteI, ReadI]> {
2886  bits<5> Rd;
2887  bits<16> imm;
2888  bits<6> shift;
2889  let Inst{30-29} = opc;
2890  let Inst{28-23} = 0b100101;
2891  let Inst{22-21} = shift{5-4};
2892  let Inst{20-5}  = imm;
2893  let Inst{4-0}   = Rd;
2894
2895  let DecoderMethod = "DecodeMoveImmInstruction";
2896}
2897
2898multiclass InsertImmediate<bits<2> opc, string asm> {
2899  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2900    let Inst{31} = 0;
2901  }
2902
2903  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2904    let Inst{31} = 1;
2905  }
2906}
2907
2908//---
2909// Add/Subtract
2910//---
2911
2912class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2913                    string asm_inst, string asm_ops,
2914                    dag inputs, dag pattern>
2915    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2916      Sched<[WriteI, ReadI]> {
2917  bits<5>  Rd;
2918  bits<5>  Rn;
2919  let Inst{30}    = isSub;
2920  let Inst{29}    = setFlags;
2921  let Inst{28-24} = 0b10001;
2922  let Inst{9-5}   = Rn;
2923  let Inst{4-0}   = Rd;
2924}
2925
2926class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2927                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2928                     string asm_inst, SDPatternOperator OpNode>
2929    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2930                    (ins srcRegtype:$Rn, immtype:$imm),
2931                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2932  bits<14> imm;
2933  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2934  let Inst{21-10} = imm{11-0};
2935  let DecoderMethod = "DecodeAddSubImmShift";
2936  let hasPostISelHook = 1;
2937}
2938
2939class BaseAddSubRegPseudo<RegisterClass regtype,
2940                          SDPatternOperator OpNode>
2941    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2942             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2943      Sched<[WriteI, ReadI, ReadI]>;
2944
2945class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2946                     arith_shifted_reg shifted_regtype, string asm,
2947                     SDPatternOperator OpNode>
2948    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2949        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2950        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2951      Sched<[WriteISReg, ReadI, ReadISReg]> {
2952  bits<5> Rd;
2953  bits<5> Rn;
2954  bits<5> Rm;
2955  bits<8> shift;
2956  let Inst{30}    = isSub;
2957  let Inst{29}    = setFlags;
2958  let Inst{28-24} = 0b01011;
2959  let Inst{23-22} = shift{7-6};
2960  let Inst{21}    = 0;
2961  let Inst{20-16} = Rm;
2962  let Inst{15-10} = shift{5-0};
2963  let Inst{9-5}   = Rn;
2964  let Inst{4-0}   = Rd;
2965
2966  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2967}
2968
2969class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2970                     RegisterClass src1Regtype, Operand src2Regtype,
2971                     string asm, SDPatternOperator OpNode>
2972    : I<(outs dstRegtype:$Rd),
2973        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2974        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2975        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2976      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2977  bits<5> Rd;
2978  bits<5> Rn;
2979  bits<5> Rm;
2980  bits<6> extend;
2981  let Inst{30}    = isSub;
2982  let Inst{29}    = setFlags;
2983  let Inst{28-24} = 0b01011;
2984  let Inst{23-21} = 0b001;
2985  let Inst{20-16} = Rm;
2986  let Inst{15-13} = extend{5-3};
2987  let Inst{12-10} = extend{2-0};
2988  let Inst{9-5}   = Rn;
2989  let Inst{4-0}   = Rd;
2990
2991  let DecoderMethod = "DecodeAddSubERegInstruction";
2992}
2993
2994let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2995class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2996                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2997                       Operand ext_op, string asm>
2998    : I<(outs dstRegtype:$Rd),
2999        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
3000        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
3001      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
3002  bits<5> Rd;
3003  bits<5> Rn;
3004  bits<5> Rm;
3005  bits<6> ext;
3006  let Inst{30}    = isSub;
3007  let Inst{29}    = setFlags;
3008  let Inst{28-24} = 0b01011;
3009  let Inst{23-21} = 0b001;
3010  let Inst{20-16} = Rm;
3011  let Inst{15}    = ext{5};
3012  let Inst{12-10} = ext{2-0};
3013  let Inst{9-5}   = Rn;
3014  let Inst{4-0}   = Rd;
3015
3016  let DecoderMethod = "DecodeAddSubERegInstruction";
3017}
3018
3019// Aliases for register+register add/subtract.
3020class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
3021                     RegisterClass src1Regtype, RegisterClass src2Regtype,
3022                     int shiftExt>
3023    : InstAlias<asm#"\t$dst, $src1, $src2",
3024                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
3025                      shiftExt)>;
3026
3027multiclass AddSub<bit isSub, string mnemonic, string alias,
3028                  SDPatternOperator OpNode = null_frag> {
3029  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
3030  // Add/Subtract immediate
3031  // Increase the weight of the immediate variant to try to match it before
3032  // the extended register variant.
3033  // We used to match the register variant before the immediate when the
3034  // register argument could be implicitly zero-extended.
3035  let AddedComplexity = 6 in
3036  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
3037                           mnemonic, OpNode> {
3038    let Inst{31} = 0;
3039  }
3040  let AddedComplexity = 6 in
3041  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
3042                           mnemonic, OpNode> {
3043    let Inst{31} = 1;
3044  }
3045
3046  // Add/Subtract register - Only used for CodeGen
3047  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
3048  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
3049
3050  // Add/Subtract shifted register
3051  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
3052                           OpNode> {
3053    let Inst{31} = 0;
3054  }
3055  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
3056                           OpNode> {
3057    let Inst{31} = 1;
3058  }
3059  }
3060
3061  // Add/Subtract extended register
3062  let AddedComplexity = 1, hasSideEffects = 0 in {
3063  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
3064                           arith_extended_reg32_i32, mnemonic, OpNode> {
3065    let Inst{31} = 0;
3066  }
3067  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
3068                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
3069    let Inst{31} = 1;
3070  }
3071  }
3072
3073  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
3074                               arith_extendlsl64, mnemonic> {
3075    // UXTX and SXTX only.
3076    let Inst{14-13} = 0b11;
3077    let Inst{31} = 1;
3078  }
3079
3080  // add Rd, Rb, -imm -> sub Rd, Rn, imm
3081  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3082                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
3083                      addsub_shifted_imm32_neg:$imm), 0>;
3084  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3085                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
3086                       addsub_shifted_imm64_neg:$imm), 0>;
3087
3088  // Register/register aliases with no shift when SP is not used.
3089  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
3090                       GPR32, GPR32, GPR32, 0>;
3091  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
3092                       GPR64, GPR64, GPR64, 0>;
3093
3094  // Register/register aliases with no shift when either the destination or
3095  // first source register is SP.
3096  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3097                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
3098  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3099                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
3100  def : AddSubRegAlias<mnemonic,
3101                       !cast<Instruction>(NAME#"Xrx64"),
3102                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
3103  def : AddSubRegAlias<mnemonic,
3104                       !cast<Instruction>(NAME#"Xrx64"),
3105                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
3106}
3107
3108multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
3109                   string alias, string cmpAlias> {
3110  let isCompare = 1, Defs = [NZCV] in {
3111  // Add/Subtract immediate
3112  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
3113                           mnemonic, OpNode> {
3114    let Inst{31} = 0;
3115  }
3116  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
3117                           mnemonic, OpNode> {
3118    let Inst{31} = 1;
3119  }
3120
3121  // Add/Subtract register
3122  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
3123  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
3124
3125  // Add/Subtract shifted register
3126  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
3127                           OpNode> {
3128    let Inst{31} = 0;
3129  }
3130  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
3131                           OpNode> {
3132    let Inst{31} = 1;
3133  }
3134
3135  // Add/Subtract extended register
3136  let AddedComplexity = 1 in {
3137  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
3138                           arith_extended_reg32_i32, mnemonic, OpNode> {
3139    let Inst{31} = 0;
3140  }
3141  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
3142                           arith_extended_reg32_i64, mnemonic, OpNode> {
3143    let Inst{31} = 1;
3144  }
3145  }
3146
3147  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
3148                               arith_extendlsl64, mnemonic> {
3149    // UXTX and SXTX only.
3150    let Inst{14-13} = 0b11;
3151    let Inst{31} = 1;
3152  }
3153  } // Defs = [NZCV]
3154
3155  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
3156  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3157                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
3158                      addsub_shifted_imm32_neg:$imm), 0>;
3159  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3160                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
3161                       addsub_shifted_imm64_neg:$imm), 0>;
3162
3163  // Compare aliases
3164  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3165                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
3166  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3167                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
3168  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
3169                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3170  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
3171                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3172  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
3173                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
3174  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
3175                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
3176  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
3177                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
3178
3179  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
3180  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3181                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
3182  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3183                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
3184
3185  // Compare shorthands
3186  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
3187                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
3188  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
3189                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
3190  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
3191                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
3192  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
3193                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
3194
3195  // Register/register aliases with no shift when SP is not used.
3196  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
3197                       GPR32, GPR32, GPR32, 0>;
3198  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
3199                       GPR64, GPR64, GPR64, 0>;
3200
3201  // Register/register aliases with no shift when the first source register
3202  // is SP.
3203  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3204                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
3205  def : AddSubRegAlias<mnemonic,
3206                       !cast<Instruction>(NAME#"Xrx64"),
3207                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
3208}
3209
3210class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
3211      : BaseAddSubImm<
3212          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
3213          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
3214          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
3215  bits<6> imm6;
3216  bits<4> imm4;
3217  let Inst{31} = 1;
3218  let Inst{23-22} = 0b10;
3219  let Inst{21-16} = imm6;
3220  let Inst{15-14} = 0b00;
3221  let Inst{13-10} = imm4;
3222  let Unpredictable{15-14} = 0b11;
3223}
3224
3225class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
3226      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
3227                             GPR64sp, GPR64sp>;
3228
3229//---
3230// Extract
3231//---
3232def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
3233                                      SDTCisPtrTy<3>]>;
3234def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
3235
3236class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
3237                     list<dag> patterns>
3238    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
3239         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
3240      Sched<[WriteExtr, ReadExtrHi]> {
3241  bits<5> Rd;
3242  bits<5> Rn;
3243  bits<5> Rm;
3244  bits<6> imm;
3245
3246  let Inst{30-23} = 0b00100111;
3247  let Inst{21}    = 0;
3248  let Inst{20-16} = Rm;
3249  let Inst{15-10} = imm;
3250  let Inst{9-5}   = Rn;
3251  let Inst{4-0}   = Rd;
3252}
3253
3254multiclass ExtractImm<string asm> {
3255  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
3256                      [(set GPR32:$Rd,
3257                        (fshr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
3258    let Inst{31} = 0;
3259    let Inst{22} = 0;
3260    // imm<5> must be zero.
3261    let imm{5}   = 0;
3262  }
3263  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
3264                      [(set GPR64:$Rd,
3265                        (fshr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
3266
3267    let Inst{31} = 1;
3268    let Inst{22} = 1;
3269  }
3270}
3271
3272//---
3273// Bitfield
3274//---
3275
3276let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3277class BaseBitfieldImm<bits<2> opc,
3278                      RegisterClass regtype, Operand imm_type, string asm>
3279    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
3280         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
3281      Sched<[WriteIS, ReadI]> {
3282  bits<5> Rd;
3283  bits<5> Rn;
3284  bits<6> immr;
3285  bits<6> imms;
3286
3287  let Inst{30-29} = opc;
3288  let Inst{28-23} = 0b100110;
3289  let Inst{21-16} = immr;
3290  let Inst{15-10} = imms;
3291  let Inst{9-5}   = Rn;
3292  let Inst{4-0}   = Rd;
3293}
3294
3295multiclass BitfieldImm<bits<2> opc, string asm> {
3296  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
3297    let Inst{31} = 0;
3298    let Inst{22} = 0;
3299    // imms<5> and immr<5> must be zero, else ReservedValue().
3300    let Inst{21} = 0;
3301    let Inst{15} = 0;
3302  }
3303  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
3304    let Inst{31} = 1;
3305    let Inst{22} = 1;
3306  }
3307}
3308
3309let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3310class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3311                      RegisterClass regtype, Operand imm_type, string asm>
3312    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3313                             imm_type:$imms),
3314         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3315      Sched<[WriteIS, ReadI]> {
3316  bits<5> Rd;
3317  bits<5> Rn;
3318  bits<6> immr;
3319  bits<6> imms;
3320
3321  let Inst{30-29} = opc;
3322  let Inst{28-23} = 0b100110;
3323  let Inst{21-16} = immr;
3324  let Inst{15-10} = imms;
3325  let Inst{9-5}   = Rn;
3326  let Inst{4-0}   = Rd;
3327}
3328
3329multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3330  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3331    let Inst{31} = 0;
3332    let Inst{22} = 0;
3333    // imms<5> and immr<5> must be zero, else ReservedValue().
3334    let Inst{21} = 0;
3335    let Inst{15} = 0;
3336  }
3337  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3338    let Inst{31} = 1;
3339    let Inst{22} = 1;
3340  }
3341}
3342
3343//---
3344// Logical
3345//---
3346
3347// Logical (immediate)
3348class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3349                     RegisterClass sregtype, Operand imm_type, string asm,
3350                     list<dag> pattern>
3351    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3352         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3353      Sched<[WriteI, ReadI]> {
3354  bits<5>  Rd;
3355  bits<5>  Rn;
3356  bits<13> imm;
3357  let Inst{30-29} = opc;
3358  let Inst{28-23} = 0b100100;
3359  let Inst{22}    = imm{12};
3360  let Inst{21-16} = imm{11-6};
3361  let Inst{15-10} = imm{5-0};
3362  let Inst{9-5}   = Rn;
3363  let Inst{4-0}   = Rd;
3364
3365  let DecoderMethod = "DecodeLogicalImmInstruction";
3366}
3367
3368// Logical (shifted register)
3369class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3370                      logical_shifted_reg shifted_regtype, string asm,
3371                      list<dag> pattern>
3372    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3373        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3374      Sched<[WriteISReg, ReadI, ReadISReg]> {
3375  bits<5> Rd;
3376  bits<5> Rn;
3377  bits<5> Rm;
3378  bits<8> shift;
3379  let Inst{30-29} = opc;
3380  let Inst{28-24} = 0b01010;
3381  let Inst{23-22} = shift{7-6};
3382  let Inst{21}    = N;
3383  let Inst{20-16} = Rm;
3384  let Inst{15-10} = shift{5-0};
3385  let Inst{9-5}   = Rn;
3386  let Inst{4-0}   = Rd;
3387
3388  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3389}
3390
3391// Aliases for register+register logical instructions.
3392class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3393    : InstAlias<asm#"\t$dst, $src1, $src2",
3394                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3395
3396multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3397                      string Alias> {
3398  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3399  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3400                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3401                                               logical_imm32:$imm))]> {
3402    let Inst{31} = 0;
3403    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3404  }
3405  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3406  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3407                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3408                                               logical_imm64:$imm))]> {
3409    let Inst{31} = 1;
3410  }
3411
3412  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3413                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3414                      logical_imm32_not:$imm), 0>;
3415  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3416                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3417                       logical_imm64_not:$imm), 0>;
3418}
3419
3420multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3421                       string Alias> {
3422  let isCompare = 1, Defs = [NZCV] in {
3423  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3424      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3425    let Inst{31} = 0;
3426    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3427  }
3428  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3429      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3430    let Inst{31} = 1;
3431  }
3432  } // end Defs = [NZCV]
3433
3434  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3435                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3436                      logical_imm32_not:$imm), 0>;
3437  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3438                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3439                       logical_imm64_not:$imm), 0>;
3440}
3441
3442class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3443    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3444             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3445      Sched<[WriteI, ReadI, ReadI]>;
3446
3447// Split from LogicalImm as not all instructions have both.
3448multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3449                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3450  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3451  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3452  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3453  }
3454
3455  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3456                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3457                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3458    let Inst{31} = 0;
3459  }
3460  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3461                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3462                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3463    let Inst{31} = 1;
3464  }
3465
3466  def : LogicalRegAlias<mnemonic,
3467                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3468  def : LogicalRegAlias<mnemonic,
3469                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3470}
3471
3472// Split from LogicalReg to allow setting NZCV Defs
3473multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3474                       SDPatternOperator OpNode = null_frag> {
3475  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3476  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3477  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3478
3479  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3480            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3481    let Inst{31} = 0;
3482  }
3483  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3484            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3485    let Inst{31} = 1;
3486  }
3487  } // Defs = [NZCV]
3488
3489  def : LogicalRegAlias<mnemonic,
3490                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3491  def : LogicalRegAlias<mnemonic,
3492                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3493}
3494
3495//---
3496// Conditionally set flags
3497//---
3498
3499let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3500class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3501                            string mnemonic, SDNode OpNode>
3502    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3503         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3504         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3505                             (i32 imm:$cond), NZCV))]>,
3506      Sched<[WriteI, ReadI]> {
3507  let Uses = [NZCV];
3508  let Defs = [NZCV];
3509
3510  bits<5> Rn;
3511  bits<5> imm;
3512  bits<4> nzcv;
3513  bits<4> cond;
3514
3515  let Inst{30}    = op;
3516  let Inst{29-21} = 0b111010010;
3517  let Inst{20-16} = imm;
3518  let Inst{15-12} = cond;
3519  let Inst{11-10} = 0b10;
3520  let Inst{9-5}   = Rn;
3521  let Inst{4}     = 0b0;
3522  let Inst{3-0}   = nzcv;
3523}
3524
3525let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3526class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3527                            SDNode OpNode>
3528    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3529         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3530         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3531                             (i32 imm:$cond), NZCV))]>,
3532      Sched<[WriteI, ReadI, ReadI]> {
3533  let Uses = [NZCV];
3534  let Defs = [NZCV];
3535
3536  bits<5> Rn;
3537  bits<5> Rm;
3538  bits<4> nzcv;
3539  bits<4> cond;
3540
3541  let Inst{30}    = op;
3542  let Inst{29-21} = 0b111010010;
3543  let Inst{20-16} = Rm;
3544  let Inst{15-12} = cond;
3545  let Inst{11-10} = 0b00;
3546  let Inst{9-5}   = Rn;
3547  let Inst{4}     = 0b0;
3548  let Inst{3-0}   = nzcv;
3549}
3550
3551multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3552  // immediate operand variants
3553  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3554    let Inst{31} = 0;
3555  }
3556  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3557    let Inst{31} = 1;
3558  }
3559  // register operand variants
3560  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3561    let Inst{31} = 0;
3562  }
3563  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3564    let Inst{31} = 1;
3565  }
3566}
3567
3568//---
3569// Conditional select
3570//---
3571
3572class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3573    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3574         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3575         [(set regtype:$Rd,
3576               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3577      Sched<[WriteI, ReadI, ReadI]> {
3578  let Uses = [NZCV];
3579
3580  bits<5> Rd;
3581  bits<5> Rn;
3582  bits<5> Rm;
3583  bits<4> cond;
3584
3585  let Inst{30}    = op;
3586  let Inst{29-21} = 0b011010100;
3587  let Inst{20-16} = Rm;
3588  let Inst{15-12} = cond;
3589  let Inst{11-10} = op2;
3590  let Inst{9-5}   = Rn;
3591  let Inst{4-0}   = Rd;
3592}
3593
3594multiclass CondSelect<bit op, bits<2> op2, string asm> {
3595  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3596    let Inst{31} = 0;
3597  }
3598  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3599    let Inst{31} = 1;
3600  }
3601}
3602
3603class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3604                       PatFrag frag>
3605    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3606         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3607         [(set regtype:$Rd,
3608               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3609               (i32 imm:$cond), NZCV))]>,
3610      Sched<[WriteI, ReadI, ReadI]> {
3611  let Uses = [NZCV];
3612
3613  bits<5> Rd;
3614  bits<5> Rn;
3615  bits<5> Rm;
3616  bits<4> cond;
3617
3618  let Inst{30}    = op;
3619  let Inst{29-21} = 0b011010100;
3620  let Inst{20-16} = Rm;
3621  let Inst{15-12} = cond;
3622  let Inst{11-10} = op2;
3623  let Inst{9-5}   = Rn;
3624  let Inst{4-0}   = Rd;
3625}
3626
3627def inv_cond_XFORM : SDNodeXForm<imm, [{
3628  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3629  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3630                                   MVT::i32);
3631}]>;
3632
3633multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3634  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3635    let Inst{31} = 0;
3636  }
3637  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3638    let Inst{31} = 1;
3639  }
3640
3641  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3642            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3643                                           (inv_cond_XFORM imm:$cond))>;
3644
3645  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3646            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3647                                           (inv_cond_XFORM imm:$cond))>;
3648}
3649
3650//---
3651// Special Mask Value
3652//---
3653def maski8_or_more : Operand<i32>,
3654  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3655}
3656def maski16_or_more : Operand<i32>,
3657  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3658}
3659
3660
3661//---
3662// Load/store
3663//---
3664
3665// (unsigned immediate)
3666// Indexed for 8-bit registers. offset is in range [0,4095].
3667def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3668def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3669def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3670def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3671def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3672
3673// (unsigned immediate)
3674// Indexed for 8-bit registers. offset is in range [0,63].
3675def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3676def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3677def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3678def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3679
3680def gi_am_indexed8 :
3681    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3682    GIComplexPatternEquiv<am_indexed8>;
3683def gi_am_indexed16 :
3684    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3685    GIComplexPatternEquiv<am_indexed16>;
3686def gi_am_indexed32 :
3687    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3688    GIComplexPatternEquiv<am_indexed32>;
3689def gi_am_indexed64 :
3690    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3691    GIComplexPatternEquiv<am_indexed64>;
3692def gi_am_indexed128 :
3693    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3694    GIComplexPatternEquiv<am_indexed128>;
3695
3696class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3697  let Name = "UImm12Offset" # Scale;
3698  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3699  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3700  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3701}
3702
3703def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3704def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3705def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3706def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3707def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3708
3709class uimm12_scaled<int Scale> : Operand<i64> {
3710  let ParserMatchClass
3711   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3712  let EncoderMethod
3713   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3714  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3715}
3716
3717def uimm12s1 : uimm12_scaled<1>;
3718def uimm12s2 : uimm12_scaled<2>;
3719def uimm12s4 : uimm12_scaled<4>;
3720def uimm12s8 : uimm12_scaled<8>;
3721def uimm12s16 : uimm12_scaled<16>;
3722
3723class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3724                      string asm, list<dag> pattern>
3725    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3726  bits<5> Rt;
3727
3728  bits<5> Rn;
3729  bits<12> offset;
3730
3731  let Inst{31-30} = sz;
3732  let Inst{29-27} = 0b111;
3733  let Inst{26}    = V;
3734  let Inst{25-24} = 0b01;
3735  let Inst{23-22} = opc;
3736  let Inst{21-10} = offset;
3737  let Inst{9-5}   = Rn;
3738  let Inst{4-0}   = Rt;
3739
3740  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3741}
3742
3743multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3744                  Operand indextype, string asm, list<dag> pattern> {
3745  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3746  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3747                           (ins GPR64sp:$Rn, indextype:$offset),
3748                           asm, pattern>,
3749           Sched<[WriteLD]>;
3750
3751  def : InstAlias<asm # "\t$Rt, [$Rn]",
3752                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3753}
3754
3755multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3756             Operand indextype, string asm, list<dag> pattern> {
3757  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3758  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3759                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3760                           asm, pattern>,
3761           Sched<[WriteST]>;
3762
3763  def : InstAlias<asm # "\t$Rt, [$Rn]",
3764                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3765}
3766
3767// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3768// substitute zero-registers automatically.
3769//
3770// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3771//       into StoreUI.
3772multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3773             Operand indextype, string asm, list<dag> pattern> {
3774  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3775  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3776                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3777                           asm, pattern>,
3778           Sched<[WriteST]>;
3779
3780  def : InstAlias<asm # "\t$Rt, [$Rn]",
3781                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3782}
3783
3784def PrefetchOperand : AsmOperandClass {
3785  let Name = "Prefetch";
3786  let ParserMethod = "tryParsePrefetch";
3787}
3788def prfop : Operand<i32> {
3789  let PrintMethod = "printPrefetchOp";
3790  let ParserMatchClass = PrefetchOperand;
3791}
3792
3793let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3794class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3795    : BaseLoadStoreUI<sz, V, opc,
3796                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3797                      asm, pat>,
3798      Sched<[WriteLD]>;
3799
3800//---
3801// Load literal
3802//---
3803
3804// Load literal address: 19-bit immediate. The low two bits of the target
3805// offset are implied zero and so are not part of the immediate.
3806def am_ldrlit : Operand<iPTR> {
3807  let EncoderMethod = "getLoadLiteralOpValue";
3808  let DecoderMethod = "DecodePCRelLabel19";
3809  let PrintMethod = "printAlignedLabel";
3810  let ParserMatchClass = PCRelLabel19Operand;
3811  let OperandType = "OPERAND_PCREL";
3812}
3813
3814let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3815class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3816    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3817        asm, "\t$Rt, $label", "", pat>,
3818      Sched<[WriteLD]> {
3819  bits<5> Rt;
3820  bits<19> label;
3821  let Inst{31-30} = opc;
3822  let Inst{29-27} = 0b011;
3823  let Inst{26}    = V;
3824  let Inst{25-24} = 0b00;
3825  let Inst{23-5}  = label;
3826  let Inst{4-0}   = Rt;
3827}
3828
3829let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3830class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3831    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3832        asm, "\t$Rt, $label", "", pat>,
3833      Sched<[WriteLD]> {
3834  bits<5> Rt;
3835  bits<19> label;
3836  let Inst{31-30} = opc;
3837  let Inst{29-27} = 0b011;
3838  let Inst{26}    = V;
3839  let Inst{25-24} = 0b00;
3840  let Inst{23-5}  = label;
3841  let Inst{4-0}   = Rt;
3842}
3843
3844//---
3845// Load/store register offset
3846//---
3847
3848def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3849def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3850def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3851def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3852def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3853
3854def gi_ro_Xindexed8 :
3855    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3856    GIComplexPatternEquiv<ro_Xindexed8>;
3857def gi_ro_Xindexed16 :
3858    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3859    GIComplexPatternEquiv<ro_Xindexed16>;
3860def gi_ro_Xindexed32 :
3861    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3862    GIComplexPatternEquiv<ro_Xindexed32>;
3863def gi_ro_Xindexed64 :
3864    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3865    GIComplexPatternEquiv<ro_Xindexed64>;
3866def gi_ro_Xindexed128 :
3867    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3868    GIComplexPatternEquiv<ro_Xindexed128>;
3869
3870def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3871def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3872def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3873def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3874def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3875
3876def gi_ro_Windexed8 :
3877    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3878    GIComplexPatternEquiv<ro_Windexed8>;
3879def gi_ro_Windexed16 :
3880    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3881    GIComplexPatternEquiv<ro_Windexed16>;
3882def gi_ro_Windexed32 :
3883    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3884    GIComplexPatternEquiv<ro_Windexed32>;
3885def gi_ro_Windexed64 :
3886    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3887    GIComplexPatternEquiv<ro_Windexed64>;
3888def gi_ro_Windexed128 :
3889    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3890    GIComplexPatternEquiv<ro_Windexed128>;
3891
3892class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3893  let Name = "Mem" # Reg # "Extend" # Width;
3894  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3895  let RenderMethod = "addMemExtendOperands";
3896  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3897}
3898
3899def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3900  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3901  // the trivial shift.
3902  let RenderMethod = "addMemExtend8Operands";
3903}
3904def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3905def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3906def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3907def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3908
3909def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3910  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3911  // the trivial shift.
3912  let RenderMethod = "addMemExtend8Operands";
3913}
3914def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3915def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3916def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3917def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3918
3919class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3920        : Operand<i32> {
3921  let ParserMatchClass = ParserClass;
3922  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3923  let DecoderMethod = "DecodeMemExtend";
3924  let EncoderMethod = "getMemExtendOpValue";
3925  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3926}
3927
3928def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3929def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3930def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3931def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3932def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3933
3934def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3935def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3936def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3937def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3938def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3939
3940class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3941                  Operand wextend, Operand xextend>  {
3942  // CodeGen-level pattern covering the entire addressing mode.
3943  ComplexPattern Wpat = windex;
3944  ComplexPattern Xpat = xindex;
3945
3946  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3947  Operand Wext = wextend;
3948  Operand Xext = xextend;
3949}
3950
3951def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3952def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3953def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3954def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3955def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3956                       ro_Xextend128>;
3957
3958class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3959                   dag outs, list<dag> pat>
3960    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3961  bits<5> Rt;
3962  bits<5> Rn;
3963  bits<5> Rm;
3964  bits<2> extend;
3965  let Inst{31-30} = sz;
3966  let Inst{29-27} = 0b111;
3967  let Inst{26}    = V;
3968  let Inst{25-24} = 0b00;
3969  let Inst{23-22} = opc;
3970  let Inst{21}    = 1;
3971  let Inst{20-16} = Rm;
3972  let Inst{15}    = extend{1}; // sign extend Rm?
3973  let Inst{14}    = 1;
3974  let Inst{12}    = extend{0}; // do shift?
3975  let Inst{11-10} = 0b10;
3976  let Inst{9-5}   = Rn;
3977  let Inst{4-0}   = Rt;
3978}
3979
3980class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3981  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3982              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3983
3984multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3985                   string asm, ValueType Ty, SDPatternOperator loadop> {
3986  let AddedComplexity = 10 in
3987  def roW : LoadStore8RO<sz, V, opc, asm,
3988                 (outs regtype:$Rt),
3989                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3990                 [(set (Ty regtype:$Rt),
3991                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3992                                             ro_Wextend8:$extend)))]>,
3993           Sched<[WriteLDIdx, ReadAdrBase]> {
3994    let Inst{13} = 0b0;
3995  }
3996
3997  let AddedComplexity = 10 in
3998  def roX : LoadStore8RO<sz, V, opc, asm,
3999                 (outs regtype:$Rt),
4000                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
4001                 [(set (Ty regtype:$Rt),
4002                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
4003                                             ro_Xextend8:$extend)))]>,
4004           Sched<[WriteLDIdx, ReadAdrBase]> {
4005    let Inst{13} = 0b1;
4006  }
4007
4008  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4009}
4010
4011multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4012                    string asm, ValueType Ty, SDPatternOperator storeop> {
4013  let AddedComplexity = 10 in
4014  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
4015                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
4016                 [(storeop (Ty regtype:$Rt),
4017                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
4018                                         ro_Wextend8:$extend))]>,
4019            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4020    let Inst{13} = 0b0;
4021  }
4022
4023  let AddedComplexity = 10 in
4024  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
4025                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
4026                 [(storeop (Ty regtype:$Rt),
4027                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
4028                                         ro_Xextend8:$extend))]>,
4029            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4030    let Inst{13} = 0b1;
4031  }
4032
4033  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4034}
4035
4036class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4037                    dag outs, list<dag> pat>
4038    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4039  bits<5> Rt;
4040  bits<5> Rn;
4041  bits<5> Rm;
4042  bits<2> extend;
4043  let Inst{31-30} = sz;
4044  let Inst{29-27} = 0b111;
4045  let Inst{26}    = V;
4046  let Inst{25-24} = 0b00;
4047  let Inst{23-22} = opc;
4048  let Inst{21}    = 1;
4049  let Inst{20-16} = Rm;
4050  let Inst{15}    = extend{1}; // sign extend Rm?
4051  let Inst{14}    = 1;
4052  let Inst{12}    = extend{0}; // do shift?
4053  let Inst{11-10} = 0b10;
4054  let Inst{9-5}   = Rn;
4055  let Inst{4-0}   = Rt;
4056}
4057
4058multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4059                    string asm, ValueType Ty, SDPatternOperator loadop> {
4060  let AddedComplexity = 10 in
4061  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
4062                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
4063                 [(set (Ty regtype:$Rt),
4064                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
4065                                              ro_Wextend16:$extend)))]>,
4066            Sched<[WriteLDIdx, ReadAdrBase]> {
4067    let Inst{13} = 0b0;
4068  }
4069
4070  let AddedComplexity = 10 in
4071  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
4072                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
4073                 [(set (Ty regtype:$Rt),
4074                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
4075                                             ro_Xextend16:$extend)))]>,
4076            Sched<[WriteLDIdx, ReadAdrBase]> {
4077    let Inst{13} = 0b1;
4078  }
4079
4080  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4081}
4082
4083multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4084                     string asm, ValueType Ty, SDPatternOperator storeop> {
4085  let AddedComplexity = 10 in
4086  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
4087                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
4088                [(storeop (Ty regtype:$Rt),
4089                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
4090                                         ro_Wextend16:$extend))]>,
4091           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4092    let Inst{13} = 0b0;
4093  }
4094
4095  let AddedComplexity = 10 in
4096  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
4097                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
4098                [(storeop (Ty regtype:$Rt),
4099                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
4100                                         ro_Xextend16:$extend))]>,
4101           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4102    let Inst{13} = 0b1;
4103  }
4104
4105  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4106}
4107
4108class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4109                    dag outs, list<dag> pat>
4110    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4111  bits<5> Rt;
4112  bits<5> Rn;
4113  bits<5> Rm;
4114  bits<2> extend;
4115  let Inst{31-30} = sz;
4116  let Inst{29-27} = 0b111;
4117  let Inst{26}    = V;
4118  let Inst{25-24} = 0b00;
4119  let Inst{23-22} = opc;
4120  let Inst{21}    = 1;
4121  let Inst{20-16} = Rm;
4122  let Inst{15}    = extend{1}; // sign extend Rm?
4123  let Inst{14}    = 1;
4124  let Inst{12}    = extend{0}; // do shift?
4125  let Inst{11-10} = 0b10;
4126  let Inst{9-5}   = Rn;
4127  let Inst{4-0}   = Rt;
4128}
4129
4130multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4131                    string asm, ValueType Ty, SDPatternOperator loadop> {
4132  let AddedComplexity = 10 in
4133  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4134                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4135                 [(set (Ty regtype:$Rt),
4136                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4137                                              ro_Wextend32:$extend)))]>,
4138           Sched<[WriteLDIdx, ReadAdrBase]> {
4139    let Inst{13} = 0b0;
4140  }
4141
4142  let AddedComplexity = 10 in
4143  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4144                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4145                 [(set (Ty regtype:$Rt),
4146                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4147                                              ro_Xextend32:$extend)))]>,
4148           Sched<[WriteLDIdx, ReadAdrBase]> {
4149    let Inst{13} = 0b1;
4150  }
4151
4152  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4153}
4154
4155multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4156                     string asm, ValueType Ty, SDPatternOperator storeop> {
4157  let AddedComplexity = 10 in
4158  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
4159                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4160                [(storeop (Ty regtype:$Rt),
4161                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4162                                         ro_Wextend32:$extend))]>,
4163            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4164    let Inst{13} = 0b0;
4165  }
4166
4167  let AddedComplexity = 10 in
4168  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
4169                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4170                [(storeop (Ty regtype:$Rt),
4171                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4172                                        ro_Xextend32:$extend))]>,
4173            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4174    let Inst{13} = 0b1;
4175  }
4176
4177  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4178}
4179
4180class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4181                    dag outs, list<dag> pat>
4182    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4183  bits<5> Rt;
4184  bits<5> Rn;
4185  bits<5> Rm;
4186  bits<2> extend;
4187  let Inst{31-30} = sz;
4188  let Inst{29-27} = 0b111;
4189  let Inst{26}    = V;
4190  let Inst{25-24} = 0b00;
4191  let Inst{23-22} = opc;
4192  let Inst{21}    = 1;
4193  let Inst{20-16} = Rm;
4194  let Inst{15}    = extend{1}; // sign extend Rm?
4195  let Inst{14}    = 1;
4196  let Inst{12}    = extend{0}; // do shift?
4197  let Inst{11-10} = 0b10;
4198  let Inst{9-5}   = Rn;
4199  let Inst{4-0}   = Rt;
4200}
4201
4202multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4203                    string asm, ValueType Ty, SDPatternOperator loadop> {
4204  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4205  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4206                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4207                [(set (Ty regtype:$Rt),
4208                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4209                                             ro_Wextend64:$extend)))]>,
4210           Sched<[WriteLDIdx, ReadAdrBase]> {
4211    let Inst{13} = 0b0;
4212  }
4213
4214  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4215  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4216                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4217                 [(set (Ty regtype:$Rt),
4218                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4219                                              ro_Xextend64:$extend)))]>,
4220           Sched<[WriteLDIdx, ReadAdrBase]> {
4221    let Inst{13} = 0b1;
4222  }
4223
4224  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4225}
4226
4227multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4228                     string asm, ValueType Ty, SDPatternOperator storeop> {
4229  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4230  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
4231                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4232                [(storeop (Ty regtype:$Rt),
4233                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4234                                         ro_Wextend64:$extend))]>,
4235            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4236    let Inst{13} = 0b0;
4237  }
4238
4239  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4240  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
4241                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4242                [(storeop (Ty regtype:$Rt),
4243                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4244                                         ro_Xextend64:$extend))]>,
4245            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4246    let Inst{13} = 0b1;
4247  }
4248
4249  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4250}
4251
4252class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4253                     dag outs, list<dag> pat>
4254    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4255  bits<5> Rt;
4256  bits<5> Rn;
4257  bits<5> Rm;
4258  bits<2> extend;
4259  let Inst{31-30} = sz;
4260  let Inst{29-27} = 0b111;
4261  let Inst{26}    = V;
4262  let Inst{25-24} = 0b00;
4263  let Inst{23-22} = opc;
4264  let Inst{21}    = 1;
4265  let Inst{20-16} = Rm;
4266  let Inst{15}    = extend{1}; // sign extend Rm?
4267  let Inst{14}    = 1;
4268  let Inst{12}    = extend{0}; // do shift?
4269  let Inst{11-10} = 0b10;
4270  let Inst{9-5}   = Rn;
4271  let Inst{4-0}   = Rt;
4272}
4273
4274multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4275                     string asm, ValueType Ty, SDPatternOperator loadop> {
4276  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4277  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4278                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4279                 [(set (Ty regtype:$Rt),
4280                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
4281                                               ro_Wextend128:$extend)))]>,
4282            Sched<[WriteLDIdx, ReadAdrBase]> {
4283    let Inst{13} = 0b0;
4284  }
4285
4286  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4287  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4288                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4289                 [(set (Ty regtype:$Rt),
4290                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
4291                                               ro_Xextend128:$extend)))]>,
4292            Sched<[WriteLDIdx, ReadAdrBase]> {
4293    let Inst{13} = 0b1;
4294  }
4295
4296  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4297}
4298
4299multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4300                      string asm> {
4301  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4302  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
4303               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4304                []>,
4305            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4306    let Inst{13} = 0b0;
4307  }
4308
4309  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4310  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4311               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4312                []>,
4313            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4314    let Inst{13} = 0b1;
4315  }
4316
4317  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4318}
4319
4320let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4321class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4322                     string asm, list<dag> pat>
4323    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4324      Sched<[WriteLD]> {
4325  bits<5> Rt;
4326  bits<5> Rn;
4327  bits<5> Rm;
4328  bits<2> extend;
4329  let Inst{31-30} = sz;
4330  let Inst{29-27} = 0b111;
4331  let Inst{26}    = V;
4332  let Inst{25-24} = 0b00;
4333  let Inst{23-22} = opc;
4334  let Inst{21}    = 1;
4335  let Inst{20-16} = Rm;
4336  let Inst{15}    = extend{1}; // sign extend Rm?
4337  let Inst{14}    = 1;
4338  let Inst{12}    = extend{0}; // do shift?
4339  let Inst{11-10} = 0b10;
4340  let Inst{9-5}   = Rn;
4341  let Inst{4-0}   = Rt;
4342  let DecoderMethod = "DecodePRFMRegInstruction";
4343  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4344  // the decoder method returns Fail, the decoder should attempt to decode the
4345  // instruction as RPRFM.
4346  let hasCompleteDecoder = 0;
4347}
4348
4349multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4350  def roW : BasePrefetchRO<sz, V, opc, (outs),
4351                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4352                asm, [(AArch64Prefetch timm:$Rt,
4353                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4354                                                    ro_Wextend64:$extend))]> {
4355    let Inst{13} = 0b0;
4356  }
4357
4358  def roX : BasePrefetchRO<sz, V, opc, (outs),
4359                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4360                asm,  [(AArch64Prefetch timm:$Rt,
4361                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4362                                                     ro_Xextend64:$extend))]> {
4363    let Inst{13} = 0b1;
4364  }
4365
4366  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4367               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4368                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4369}
4370
4371//---
4372// Load/store unscaled immediate
4373//---
4374
4375def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4376def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4377def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4378def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4379def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4380
4381def gi_am_unscaled8 :
4382    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4383    GIComplexPatternEquiv<am_unscaled8>;
4384def gi_am_unscaled16 :
4385    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4386    GIComplexPatternEquiv<am_unscaled16>;
4387def gi_am_unscaled32 :
4388    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4389    GIComplexPatternEquiv<am_unscaled32>;
4390def gi_am_unscaled64 :
4391    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4392    GIComplexPatternEquiv<am_unscaled64>;
4393def gi_am_unscaled128 :
4394    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4395    GIComplexPatternEquiv<am_unscaled128>;
4396
4397
4398class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4399                           string asm, list<dag> pattern>
4400    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4401  bits<5> Rt;
4402  bits<5> Rn;
4403  bits<9> offset;
4404  let Inst{31-30} = sz;
4405  let Inst{29-27} = 0b111;
4406  let Inst{26}    = V;
4407  let Inst{25-24} = 0b00;
4408  let Inst{23-22} = opc;
4409  let Inst{21}    = 0;
4410  let Inst{20-12} = offset;
4411  let Inst{11-10} = 0b00;
4412  let Inst{9-5}   = Rn;
4413  let Inst{4-0}   = Rt;
4414
4415  let DecoderMethod = "DecodeSignedLdStInstruction";
4416}
4417
4418// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4419multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4420                              DAGOperand regtype > {
4421  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4422                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4423          Sched<[WriteST]> {
4424    let Inst{29} = 0;
4425    let Inst{24} = 1;
4426  }
4427  def : InstAlias<asm # "\t$Rt, [$Rn]",
4428                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4429}
4430
4431multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4432                               DAGOperand regtype > {
4433  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4434                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4435                               asm, []>,
4436          Sched<[WriteST]> {
4437    let Inst{29} = 0;
4438    let Inst{24} = 1;
4439  }
4440  def : InstAlias<asm # "\t$Rt, [$Rn]",
4441                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4442}
4443
4444multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4445                   string asm, list<dag> pattern> {
4446  let AddedComplexity = 1 in // try this before LoadUI
4447  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4448                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4449          Sched<[WriteLD]>;
4450
4451  def : InstAlias<asm # "\t$Rt, [$Rn]",
4452                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4453}
4454
4455multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4456                         string asm, list<dag> pattern> {
4457  let AddedComplexity = 1 in // try this before StoreUI
4458  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4459                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4460                               asm, pattern>,
4461          Sched<[WriteST]>;
4462
4463  def : InstAlias<asm # "\t$Rt, [$Rn]",
4464                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4465}
4466
4467multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4468                            list<dag> pat> {
4469  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4470  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4471                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4472                               asm, pat>,
4473          Sched<[WriteLD]>;
4474
4475  def : InstAlias<asm # "\t$Rt, [$Rn]",
4476                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4477}
4478
4479//---
4480// Load/store unscaled immediate, unprivileged
4481//---
4482
4483class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4484                                dag oops, dag iops, string asm>
4485    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4486  bits<5> Rt;
4487  bits<5> Rn;
4488  bits<9> offset;
4489  let Inst{31-30} = sz;
4490  let Inst{29-27} = 0b111;
4491  let Inst{26}    = V;
4492  let Inst{25-24} = 0b00;
4493  let Inst{23-22} = opc;
4494  let Inst{21}    = 0;
4495  let Inst{20-12} = offset;
4496  let Inst{11-10} = 0b10;
4497  let Inst{9-5}   = Rn;
4498  let Inst{4-0}   = Rt;
4499
4500  let DecoderMethod = "DecodeSignedLdStInstruction";
4501}
4502
4503multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4504                            RegisterClass regtype, string asm> {
4505  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4506  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4507                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4508          Sched<[WriteLD]>;
4509
4510  def : InstAlias<asm # "\t$Rt, [$Rn]",
4511                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4512}
4513
4514multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4515                             RegisterClass regtype, string asm> {
4516  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4517  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4518                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4519                                 asm>,
4520          Sched<[WriteST]>;
4521
4522  def : InstAlias<asm # "\t$Rt, [$Rn]",
4523                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4524}
4525
4526//---
4527// Load/store pre-indexed
4528//---
4529
4530class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4531                          string asm, string cstr, list<dag> pat>
4532    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4533  bits<5> Rt;
4534  bits<5> Rn;
4535  bits<9> offset;
4536  let Inst{31-30} = sz;
4537  let Inst{29-27} = 0b111;
4538  let Inst{26}    = V;
4539  let Inst{25-24} = 0;
4540  let Inst{23-22} = opc;
4541  let Inst{21}    = 0;
4542  let Inst{20-12} = offset;
4543  let Inst{11-10} = 0b11;
4544  let Inst{9-5}   = Rn;
4545  let Inst{4-0}   = Rt;
4546
4547  let DecoderMethod = "DecodeSignedLdStInstruction";
4548}
4549
4550let hasSideEffects = 0 in {
4551let mayStore = 0, mayLoad = 1 in
4552class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4553             string asm>
4554    : BaseLoadStorePreIdx<sz, V, opc,
4555                     (outs GPR64sp:$wback, regtype:$Rt),
4556                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4557                     "$Rn = $wback,@earlyclobber $wback", []>,
4558      Sched<[WriteAdr, WriteLD]>;
4559
4560let mayStore = 1, mayLoad = 0 in
4561class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4562                  string asm, SDPatternOperator storeop, ValueType Ty>
4563    : BaseLoadStorePreIdx<sz, V, opc,
4564                      (outs GPR64sp:$wback),
4565                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4566                      asm, "$Rn = $wback,@earlyclobber $wback",
4567      [(set GPR64sp:$wback,
4568            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4569      Sched<[WriteAdr, WriteST]>;
4570} // hasSideEffects = 0
4571
4572//---
4573// Load/store post-indexed
4574//---
4575
4576class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4577                          string asm, string cstr, list<dag> pat>
4578    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4579  bits<5> Rt;
4580  bits<5> Rn;
4581  bits<9> offset;
4582  let Inst{31-30} = sz;
4583  let Inst{29-27} = 0b111;
4584  let Inst{26}    = V;
4585  let Inst{25-24} = 0b00;
4586  let Inst{23-22} = opc;
4587  let Inst{21}    = 0b0;
4588  let Inst{20-12} = offset;
4589  let Inst{11-10} = 0b01;
4590  let Inst{9-5}   = Rn;
4591  let Inst{4-0}   = Rt;
4592
4593  let DecoderMethod = "DecodeSignedLdStInstruction";
4594}
4595
4596let hasSideEffects = 0 in {
4597let mayStore = 0, mayLoad = 1 in
4598class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4599             string asm>
4600    : BaseLoadStorePostIdx<sz, V, opc,
4601                      (outs GPR64sp:$wback, regtype:$Rt),
4602                      (ins GPR64sp:$Rn, simm9:$offset),
4603                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4604      Sched<[WriteAdr, WriteLD]>;
4605
4606let mayStore = 1, mayLoad = 0 in
4607class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4608                   string asm, SDPatternOperator storeop, ValueType Ty>
4609    : BaseLoadStorePostIdx<sz, V, opc,
4610                      (outs GPR64sp:$wback),
4611                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4612                       asm, "$Rn = $wback,@earlyclobber $wback",
4613      [(set GPR64sp:$wback,
4614            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4615    Sched<[WriteAdr, WriteST]>;
4616} // hasSideEffects = 0
4617
4618
4619//---
4620// Load/store pair
4621//---
4622
4623// (indexed, offset)
4624
4625class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4626                              string asm>
4627    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4628  bits<5> Rt;
4629  bits<5> Rt2;
4630  bits<5> Rn;
4631  bits<7> offset;
4632  let Inst{31-30} = opc;
4633  let Inst{29-27} = 0b101;
4634  let Inst{26}    = V;
4635  let Inst{25-23} = 0b010;
4636  let Inst{22}    = L;
4637  let Inst{21-15} = offset;
4638  let Inst{14-10} = Rt2;
4639  let Inst{9-5}   = Rn;
4640  let Inst{4-0}   = Rt;
4641
4642  let DecoderMethod = "DecodePairLdStInstruction";
4643}
4644
4645multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4646                          Operand indextype, string asm> {
4647  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4648  def i : BaseLoadStorePairOffset<opc, V, 1,
4649                                  (outs regtype:$Rt, regtype:$Rt2),
4650                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4651          Sched<[WriteLD, WriteLDHi]>;
4652
4653  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4654                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4655                                                  GPR64sp:$Rn, 0)>;
4656}
4657
4658
4659multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4660                           Operand indextype, string asm> {
4661  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4662  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4663                                  (ins regtype:$Rt, regtype:$Rt2,
4664                                       GPR64sp:$Rn, indextype:$offset),
4665                                  asm>,
4666          Sched<[WriteSTP]>;
4667
4668  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4669                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4670                                                  GPR64sp:$Rn, 0)>;
4671}
4672
4673// (pre-indexed)
4674class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4675                              string asm>
4676    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4677  bits<5> Rt;
4678  bits<5> Rt2;
4679  bits<5> Rn;
4680  bits<7> offset;
4681  let Inst{31-30} = opc;
4682  let Inst{29-27} = 0b101;
4683  let Inst{26}    = V;
4684  let Inst{25-23} = 0b011;
4685  let Inst{22}    = L;
4686  let Inst{21-15} = offset;
4687  let Inst{14-10} = Rt2;
4688  let Inst{9-5}   = Rn;
4689  let Inst{4-0}   = Rt;
4690
4691  let DecoderMethod = "DecodePairLdStInstruction";
4692}
4693
4694let hasSideEffects = 0 in {
4695let mayStore = 0, mayLoad = 1 in
4696class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4697                     Operand indextype, string asm>
4698    : BaseLoadStorePairPreIdx<opc, V, 1,
4699                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4700                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4701      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4702
4703let mayStore = 1, mayLoad = 0 in
4704class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4705                      Operand indextype, string asm>
4706    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4707                             (ins regtype:$Rt, regtype:$Rt2,
4708                                  GPR64sp:$Rn, indextype:$offset),
4709                             asm>,
4710      Sched<[WriteAdr, WriteSTP]>;
4711} // hasSideEffects = 0
4712
4713// (post-indexed)
4714
4715class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4716                              string asm>
4717    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4718  bits<5> Rt;
4719  bits<5> Rt2;
4720  bits<5> Rn;
4721  bits<7> offset;
4722  let Inst{31-30} = opc;
4723  let Inst{29-27} = 0b101;
4724  let Inst{26}    = V;
4725  let Inst{25-23} = 0b001;
4726  let Inst{22}    = L;
4727  let Inst{21-15} = offset;
4728  let Inst{14-10} = Rt2;
4729  let Inst{9-5}   = Rn;
4730  let Inst{4-0}   = Rt;
4731
4732  let DecoderMethod = "DecodePairLdStInstruction";
4733}
4734
4735let hasSideEffects = 0 in {
4736let mayStore = 0, mayLoad = 1 in
4737class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4738                      Operand idxtype, string asm>
4739    : BaseLoadStorePairPostIdx<opc, V, 1,
4740                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4741                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4742      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4743
4744let mayStore = 1, mayLoad = 0 in
4745class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4746                       Operand idxtype, string asm>
4747    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4748                             (ins regtype:$Rt, regtype:$Rt2,
4749                                  GPR64sp:$Rn, idxtype:$offset),
4750                             asm>,
4751      Sched<[WriteAdr, WriteSTP]>;
4752} // hasSideEffects = 0
4753
4754//  (no-allocate)
4755
4756class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4757                              string asm>
4758    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4759  bits<5> Rt;
4760  bits<5> Rt2;
4761  bits<5> Rn;
4762  bits<7> offset;
4763  let Inst{31-30} = opc;
4764  let Inst{29-27} = 0b101;
4765  let Inst{26}    = V;
4766  let Inst{25-23} = 0b000;
4767  let Inst{22}    = L;
4768  let Inst{21-15} = offset;
4769  let Inst{14-10} = Rt2;
4770  let Inst{9-5}   = Rn;
4771  let Inst{4-0}   = Rt;
4772
4773  let DecoderMethod = "DecodePairLdStInstruction";
4774}
4775
4776multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4777                           Operand indextype, string asm> {
4778  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4779  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4780                                   (outs regtype:$Rt, regtype:$Rt2),
4781                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4782          Sched<[WriteLD, WriteLDHi]>;
4783
4784
4785  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4786                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4787                                                  GPR64sp:$Rn, 0)>;
4788}
4789
4790multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4791                      Operand indextype, string asm> {
4792  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4793  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4794                                   (ins regtype:$Rt, regtype:$Rt2,
4795                                        GPR64sp:$Rn, indextype:$offset),
4796                                   asm>,
4797          Sched<[WriteSTP]>;
4798
4799  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4800                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4801                                                  GPR64sp:$Rn, 0)>;
4802}
4803
4804//  armv9.6-a load/store no-allocate pair FEAT_LSUI (no-allocate)
4805
4806class BaseLoadStorePairNoAllocLSUI<bits<2> opc, bit V, bit L, dag oops, dag iops,
4807                              string asm>
4808    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4809  bits<5> Rt;
4810  bits<5> Rt2;
4811  bits<5> Rn;
4812  bits<7> offset;
4813  let Inst{31-30} = opc;
4814  let Inst{29-27} = 0b101;
4815  let Inst{26}    = V;
4816  let Inst{25-23} = 0b000;
4817  let Inst{22}    = L;
4818  let Inst{21-15} = offset;
4819  let Inst{14-10} = Rt2;
4820  let Inst{9-5}   = Rn;
4821  let Inst{4-0}   = Rt;
4822
4823  let DecoderMethod = "DecodePairLdStInstruction";
4824}
4825
4826multiclass LoadPairNoAllocLSUI<bits<2> opc, bit V, DAGOperand regtype,
4827                           Operand indextype, string asm> {
4828  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4829  def i : BaseLoadStorePairNoAllocLSUI<opc, V, 1,
4830                                   (outs regtype:$Rt, regtype:$Rt2),
4831                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4832          Sched<[WriteLD, WriteLDHi]>;
4833
4834
4835  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4836                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4837                                                  GPR64sp:$Rn, 0)>;
4838}
4839
4840multiclass StorePairNoAllocLSUI<bits<2> opc, bit V, DAGOperand regtype,
4841                      Operand indextype, string asm> {
4842  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4843  def i : BaseLoadStorePairNoAllocLSUI<opc, V, 0, (outs),
4844                                   (ins regtype:$Rt, regtype:$Rt2,
4845                                        GPR64sp:$Rn, indextype:$offset),
4846                                   asm>,
4847          Sched<[WriteSTP]>;
4848
4849  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4850                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4851                                                  GPR64sp:$Rn, 0)>;
4852}
4853
4854//---
4855// Load/store exclusive
4856//---
4857
4858// True exclusive operations write to and/or read from the system's exclusive
4859// monitors, which as far as a compiler is concerned can be modelled as a
4860// random shared memory address. Hence LoadExclusive mayStore.
4861//
4862// Since these instructions have the undefined register bits set to 1 in
4863// their canonical form, we need a post encoder method to set those bits
4864// to 1 when encoding these instructions. We do this using the
4865// fixLoadStoreExclusive function. This function has template parameters:
4866//
4867// fixLoadStoreExclusive<int hasRs, int hasRt2>
4868//
4869// hasRs indicates that the instruction uses the Rs field, so we won't set
4870// it to 1 (and the same for Rt2). We don't need template parameters for
4871// the other register fields since Rt and Rn are always used.
4872//
4873let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4874class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4875                             dag oops, dag iops, string asm, string operands>
4876    : I<oops, iops, asm, operands, "", []> {
4877  let Inst{31-30} = sz;
4878  let Inst{29-24} = 0b001000;
4879  let Inst{23}    = o2;
4880  let Inst{22}    = L;
4881  let Inst{21}    = o1;
4882  let Inst{15}    = o0;
4883
4884  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4885}
4886
4887// Neither Rs nor Rt2 operands.
4888class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4889                               dag oops, dag iops, string asm, string operands>
4890    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4891  bits<5> Rt;
4892  bits<5> Rn;
4893  let Inst{20-16} = 0b11111;
4894  let Unpredictable{20-16} = 0b11111;
4895  let Inst{14-10} = 0b11111;
4896  let Unpredictable{14-10} = 0b11111;
4897  let Inst{9-5} = Rn;
4898  let Inst{4-0} = Rt;
4899
4900  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4901}
4902
4903// Simple load acquires don't set the exclusive monitor
4904let mayLoad = 1, mayStore = 0 in
4905class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4906                  RegisterClass regtype, string asm>
4907    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4908                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4909      Sched<[WriteLD]>;
4910
4911class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4912                    RegisterClass regtype, string asm>
4913    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4914                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4915      Sched<[WriteLD]>;
4916
4917class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4918                       RegisterClass regtype, string asm>
4919    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4920                             (outs regtype:$Rt, regtype:$Rt2),
4921                             (ins GPR64sp0:$Rn), asm,
4922                             "\t$Rt, $Rt2, [$Rn]">,
4923      Sched<[WriteLD, WriteLDHi]> {
4924  bits<5> Rt;
4925  bits<5> Rt2;
4926  bits<5> Rn;
4927  let Inst{20-16} = 0b11111;
4928  let Unpredictable{20-16} = 0b11111;
4929  let Inst{14-10} = Rt2;
4930  let Inst{9-5} = Rn;
4931  let Inst{4-0} = Rt;
4932
4933  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4934}
4935
4936// Armv9.6-a load-store exclusive instructions
4937let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4938class BaseLoadStoreExclusiveLSUI<bits<2> sz, bit L, bit o0,
4939                             dag oops, dag iops, string asm, string operands>
4940    : I<oops, iops, asm, operands, "", []> {
4941  let Inst{31-30} = sz;
4942  let Inst{29-23} = 0b0010010;
4943  let Inst{22}    = L;
4944  let Inst{21}    = 0b0;
4945  let Inst{15}    = o0;
4946}
4947
4948
4949// Neither Rs nor Rt2 operands.
4950
4951class LoadExclusiveLSUI<bits<2> sz, bit L, bit o0,
4952                    RegisterClass regtype, string asm>
4953    : BaseLoadStoreExclusiveLSUI<sz, L, o0, (outs regtype:$Rt),
4954                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4955      Sched<[WriteLD]>
4956{
4957  bits<5> Rt;
4958  bits<5> Rn;
4959  let Inst{20-16} = 0b11111;
4960  let Unpredictable{20-16} = 0b11111;
4961  let Inst{14-10} = 0b11111;
4962  let Unpredictable{14-10} = 0b11111;
4963  let Inst{9-5} = Rn;
4964  let Inst{4-0} = Rt;
4965
4966  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4967}
4968
4969 class StoreExclusiveLSUI<bits<2> sz, bit L, bit o0,
4970                      RegisterClass regtype, string asm>
4971     : BaseLoadStoreExclusiveLSUI<sz, L, o0, (outs GPR32:$Ws),
4972                              (ins regtype:$Rt, GPR64sp0:$Rn),
4973                              asm, "\t$Ws, $Rt, [$Rn]">,
4974       Sched<[WriteSTX]> {
4975   bits<5> Ws;
4976   bits<5> Rt;
4977   bits<5> Rn;
4978   let Inst{20-16} = Ws;
4979   let Inst{15} = o0;
4980   let Inst{14-10} = 0b11111;
4981   let Unpredictable{14-10} = 0b11111;
4982   let Inst{9-5} = Rn;
4983   let Inst{4-0} = Rt;
4984
4985   let Constraints = "@earlyclobber $Ws";
4986   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4987 }
4988
4989// Armv9.6-a load-store unprivileged instructions
4990class BaseLoadUnprivilegedLSUI<bits<2> sz, dag oops, dag iops, string asm>
4991    : I<oops, iops, asm, "\t$Rt, [$Rn]", "", []> {
4992   bits<5> Rt;
4993   bits<5> Rn;
4994   let Inst{31-30} = sz;
4995   let Inst{29-23} = 0b0010010;
4996   let Inst{22}  = 0b1;
4997   let Inst{21} = 0b0;
4998   let Inst{20-16} = 0b11111;
4999   let Unpredictable{20-16} = 0b11111;
5000   let Inst{15} = 0b0;
5001   let Inst{14-10} = 0b11111;
5002   let Unpredictable{14-10} = 0b11111;
5003   let Inst{9-5} = Rn;
5004   let Inst{4-0} = Rt;
5005   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
5006}
5007
5008multiclass LoadUnprivilegedLSUI<bits<2> sz, RegisterClass regtype, string asm> {
5009  def r : BaseLoadUnprivilegedLSUI<sz, (outs regtype:$Rt),
5010                                    (ins GPR64sp0:$Rn), asm>,
5011          Sched<[WriteLD]>;
5012
5013}
5014
5015class BaseStoreUnprivilegedLSUI<bits<2> sz, dag oops, dag iops, string asm>
5016    : I<oops, iops, asm, "\t$Ws, $Rt, [$Rn]", "", []> {
5017   bits<5> Rt;
5018   bits<5> Rn;
5019   bits<5> Ws;
5020   let Inst{31-30} = sz;
5021   let Inst{29-23} = 0b0010010;
5022   let Inst{22}  = 0b0;
5023   let Inst{21} = 0b0;
5024   let Inst{20-16} = Ws;
5025   let Inst{15} = 0b0;
5026   let Inst{14-10} = 0b11111;
5027   let Unpredictable{14-10} = 0b11111;
5028   let Inst{9-5} = Rn;
5029   let Inst{4-0} = Rt;
5030   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
5031   let mayStore = 1;
5032}
5033
5034multiclass StoreUnprivilegedLSUI<bits<2> sz, RegisterClass regtype, string asm> {
5035  def r : BaseStoreUnprivilegedLSUI<sz, (outs GPR32: $Ws),
5036                                 (ins regtype:$Rt, GPR64sp0:$Rn),
5037                                 asm>,
5038          Sched<[WriteSTX]>;
5039}
5040
5041// Simple store release operations do not check the exclusive monitor.
5042let mayLoad = 0, mayStore = 1 in
5043class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
5044                   RegisterClass regtype, string asm>
5045    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
5046                               (ins regtype:$Rt, GPR64sp:$Rn),
5047                               asm, "\t$Rt, [$Rn]">,
5048      Sched<[WriteST]>;
5049
5050let mayLoad = 1, mayStore = 1 in
5051class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
5052                     RegisterClass regtype, string asm>
5053    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
5054                             (ins regtype:$Rt, GPR64sp0:$Rn),
5055                             asm, "\t$Ws, $Rt, [$Rn]">,
5056      Sched<[WriteSTX]> {
5057  bits<5> Ws;
5058  bits<5> Rt;
5059  bits<5> Rn;
5060  let Inst{20-16} = Ws;
5061  let Inst{9-5} = Rn;
5062  let Inst{4-0} = Rt;
5063
5064  let Constraints = "@earlyclobber $Ws";
5065  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
5066}
5067
5068class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
5069                         RegisterClass regtype, string asm>
5070    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
5071                             (outs GPR32:$Ws),
5072                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
5073                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
5074      Sched<[WriteSTX]> {
5075  bits<5> Ws;
5076  bits<5> Rt;
5077  bits<5> Rt2;
5078  bits<5> Rn;
5079  let Inst{20-16} = Ws;
5080  let Inst{14-10} = Rt2;
5081  let Inst{9-5} = Rn;
5082  let Inst{4-0} = Rt;
5083
5084  let Constraints = "@earlyclobber $Ws";
5085}
5086
5087// Armv8.5-A Memory Tagging Extension
5088class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
5089                 string asm_opnds, string cstr, dag oops, dag iops>
5090    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
5091      Sched<[]> {
5092  bits<5> Rn;
5093
5094  let Inst{31-24} = 0b11011001;
5095  let Inst{23-22} = opc1;
5096  let Inst{21}    = 1;
5097  // Inst{20-12} defined by subclass
5098  let Inst{11-10} = opc2;
5099  let Inst{9-5}   = Rn;
5100  // Inst{4-0} defined by subclass
5101}
5102
5103class MemTagVector<bit Load, string asm_insn, string asm_opnds,
5104                   dag oops, dag iops>
5105    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
5106                  "", oops, iops> {
5107  bits<5> Rt;
5108
5109  let Inst{20-12} = 0b000000000;
5110  let Inst{4-0}   = Rt;
5111
5112  let mayLoad = Load;
5113}
5114
5115class MemTagLoad<string asm_insn, string asm_opnds>
5116    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
5117                 (outs GPR64:$wback),
5118                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
5119  bits<5> Rt;
5120  bits<9> offset;
5121
5122  let Inst{20-12} = offset;
5123  let Inst{4-0}   = Rt;
5124
5125  let mayLoad = 1;
5126}
5127
5128class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
5129                     string asm_opnds, string cstr, dag oops, dag iops>
5130    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
5131  bits<5> Rt;
5132  bits<9> offset;
5133
5134  let Inst{20-12} = offset;
5135  let Inst{4-0}   = Rt;
5136
5137  let mayStore = 1;
5138}
5139
5140multiclass MemTagStore<bits<2> opc1, string insn> {
5141  def i :
5142    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
5143                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
5144  def PreIndex :
5145    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
5146                    "$Rn = $wback",
5147                    (outs GPR64sp:$wback),
5148                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
5149  def PostIndex :
5150    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
5151                    "$Rn = $wback",
5152                    (outs GPR64sp:$wback),
5153                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
5154
5155  def : InstAlias<insn # "\t$Rt, [$Rn]",
5156                  (!cast<Instruction>(NAME # "i") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
5157}
5158
5159//---
5160// Exception generation
5161//---
5162
5163let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
5164class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
5165                          list<dag> pattern = []>
5166    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
5167      Sched<[WriteSys]> {
5168  bits<16> imm;
5169  let Inst{31-24} = 0b11010100;
5170  let Inst{23-21} = op1;
5171  let Inst{20-5}  = imm;
5172  let Inst{4-2}   = 0b000;
5173  let Inst{1-0}   = ll;
5174}
5175
5176//---
5177// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
5178//--
5179let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
5180class UDFType<bits<16> opc, string asm>
5181  : I<(outs), (ins uimm16:$imm),
5182       asm, "\t$imm", "", []>,
5183    Sched<[]> {
5184  bits<16> imm;
5185  let Inst{31-16} = opc;
5186  let Inst{15-0} = imm;
5187}
5188}
5189let Predicates = [HasFPARMv8] in {
5190
5191//---
5192// Floating point to integer conversion
5193//---
5194
5195let mayRaiseFPException = 1, Uses = [FPCR] in
5196class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
5197                      RegisterClass srcType, RegisterClass dstType,
5198                      string asm, list<dag> pattern>
5199    : I<(outs dstType:$Rd), (ins srcType:$Rn),
5200         asm, "\t$Rd, $Rn", "", pattern>,
5201      Sched<[WriteFCvt]> {
5202  bits<5> Rd;
5203  bits<5> Rn;
5204  let Inst{30-29} = 0b00;
5205  let Inst{28-24} = 0b11110;
5206  let Inst{23-22} = type;
5207  let Inst{21}    = 1;
5208  let Inst{20-19} = rmode;
5209  let Inst{18-16} = opcode;
5210  let Inst{15-10} = 0;
5211  let Inst{9-5}   = Rn;
5212  let Inst{4-0}   = Rd;
5213}
5214
5215let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5216class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
5217                      RegisterClass srcType, RegisterClass dstType,
5218                      Operand immType, string asm, list<dag> pattern>
5219    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
5220         asm, "\t$Rd, $Rn, $scale", "", pattern>,
5221      Sched<[WriteFCvt]> {
5222  bits<5> Rd;
5223  bits<5> Rn;
5224  bits<6> scale;
5225  let Inst{30-29} = 0b00;
5226  let Inst{28-24} = 0b11110;
5227  let Inst{23-22} = type;
5228  let Inst{21}    = 0;
5229  let Inst{20-19} = rmode;
5230  let Inst{18-16} = opcode;
5231  let Inst{15-10} = scale;
5232  let Inst{9-5}   = Rn;
5233  let Inst{4-0}   = Rd;
5234}
5235
5236multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
5237           SDPatternOperator OpN> {
5238  // Unscaled half-precision to 32-bit
5239  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
5240                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
5241    let Inst{31} = 0; // 32-bit GPR flag
5242    let Predicates = [HasFullFP16];
5243  }
5244
5245  // Unscaled half-precision to 64-bit
5246  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
5247                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
5248    let Inst{31} = 1; // 64-bit GPR flag
5249    let Predicates = [HasFullFP16];
5250  }
5251
5252  // Unscaled single-precision to 32-bit
5253  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
5254                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
5255    let Inst{31} = 0; // 32-bit GPR flag
5256  }
5257
5258  // Unscaled single-precision to 64-bit
5259  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
5260                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
5261    let Inst{31} = 1; // 64-bit GPR flag
5262  }
5263
5264  // Unscaled double-precision to 32-bit
5265  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
5266                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
5267    let Inst{31} = 0; // 32-bit GPR flag
5268  }
5269
5270  // Unscaled double-precision to 64-bit
5271  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
5272                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
5273    let Inst{31} = 1; // 64-bit GPR flag
5274  }
5275}
5276
5277multiclass FPToIntegerSIMDScalar<bits<2> rmode, bits<3> opcode, string asm> {
5278  // double-precision to 32-bit SIMD/FPR
5279  def SDr :  BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, FPR32, asm,
5280                                     []> {
5281    let Inst{31} = 0; // 32-bit FPR flag
5282  }
5283
5284  // half-precision to 32-bit SIMD/FPR
5285  def SHr :  BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, FPR32, asm,
5286                                     []> {
5287    let Inst{31} = 0; // 32-bit FPR flag
5288  }
5289
5290  // half-precision to 64-bit SIMD/FPR
5291  def DHr :  BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, FPR64, asm,
5292                                     []> {
5293    let Inst{31} = 1; // 64-bit FPR flag
5294  }
5295
5296  // single-precision to 64-bit SIMD/FPR
5297  def DSr :  BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, FPR64, asm,
5298                                     []> {
5299    let Inst{31} = 1; // 64-bit FPR flag
5300  }
5301}
5302
5303multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
5304                             SDPatternOperator OpN> {
5305  // Scaled half-precision to 32-bit
5306  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
5307                              fixedpoint_f16_i32, asm,
5308              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5309                                          fixedpoint_f16_i32:$scale)))]> {
5310    let Inst{31} = 0; // 32-bit GPR flag
5311    let scale{5} = 1;
5312    let Predicates = [HasFullFP16];
5313  }
5314
5315  // Scaled half-precision to 64-bit
5316  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
5317                              fixedpoint_f16_i64, asm,
5318              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5319                                          fixedpoint_f16_i64:$scale)))]> {
5320    let Inst{31} = 1; // 64-bit GPR flag
5321    let Predicates = [HasFullFP16];
5322  }
5323
5324  // Scaled single-precision to 32-bit
5325  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
5326                              fixedpoint_f32_i32, asm,
5327              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
5328                                          fixedpoint_f32_i32:$scale)))]> {
5329    let Inst{31} = 0; // 32-bit GPR flag
5330    let scale{5} = 1;
5331  }
5332
5333  // Scaled single-precision to 64-bit
5334  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
5335                              fixedpoint_f32_i64, asm,
5336              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
5337                                          fixedpoint_f32_i64:$scale)))]> {
5338    let Inst{31} = 1; // 64-bit GPR flag
5339  }
5340
5341  // Scaled double-precision to 32-bit
5342  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
5343                              fixedpoint_f64_i32, asm,
5344              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
5345                                          fixedpoint_f64_i32:$scale)))]> {
5346    let Inst{31} = 0; // 32-bit GPR flag
5347    let scale{5} = 1;
5348  }
5349
5350  // Scaled double-precision to 64-bit
5351  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
5352                              fixedpoint_f64_i64, asm,
5353              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
5354                                          fixedpoint_f64_i64:$scale)))]> {
5355    let Inst{31} = 1; // 64-bit GPR flag
5356  }
5357}
5358
5359//---
5360// Integer to floating point conversion
5361//---
5362
5363let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5364class BaseIntegerToFP<bits<2> rmode, bits<3> opcode,
5365                      RegisterClass srcType, RegisterClass dstType,
5366                      Operand immType, string asm, list<dag> pattern>
5367    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
5368         asm, "\t$Rd, $Rn, $scale", "", pattern>,
5369      Sched<[WriteFCvt]> {
5370  bits<5> Rd;
5371  bits<5> Rn;
5372  bits<6> scale;
5373  let Inst{30-24} = 0b0011110;
5374  let Inst{21}    = 0b0;
5375  let Inst{20-19} = rmode;
5376  let Inst{18-16} = opcode;
5377  let Inst{15-10} = scale;
5378  let Inst{9-5}   = Rn;
5379  let Inst{4-0}   = Rd;
5380}
5381
5382let mayRaiseFPException = 1, Uses = [FPCR] in
5383class BaseIntegerToFPUnscaled<bits<2> rmode, bits<3> opcode,
5384                      RegisterClass srcType, RegisterClass dstType,
5385                      ValueType dvt, string asm, SDPatternOperator node>
5386    : I<(outs dstType:$Rd), (ins srcType:$Rn),
5387         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
5388      Sched<[WriteFCvt]> {
5389  bits<5> Rd;
5390  bits<5> Rn;
5391  bits<6> scale;
5392  let Inst{30-24} = 0b0011110;
5393  let Inst{21}    = 0b1;
5394  let Inst{20-19} = rmode;
5395  let Inst{18-16} = opcode;
5396  let Inst{15-10} = 0b000000;
5397  let Inst{9-5}   = Rn;
5398  let Inst{4-0}   = Rd;
5399}
5400
5401multiclass IntegerToFP<bits<2> rmode, bits<3> opcode, string asm, SDPatternOperator node> {
5402  // Unscaled
5403  def UWHri: BaseIntegerToFPUnscaled<rmode, opcode, GPR32, FPR16, f16, asm, node> {
5404    let Inst{31} = 0; // 32-bit GPR flag
5405    let Inst{23-22} = 0b11; // 16-bit FPR flag
5406    let Predicates = [HasFullFP16];
5407  }
5408
5409  def UWSri: BaseIntegerToFPUnscaled<rmode, opcode, GPR32, FPR32, f32, asm, node> {
5410    let Inst{31} = 0; // 32-bit GPR flag
5411    let Inst{23-22} = 0b00; // 32-bit FPR flag
5412  }
5413
5414  def UWDri: BaseIntegerToFPUnscaled<rmode, opcode, GPR32, FPR64, f64, asm, node> {
5415    let Inst{31} = 0; // 32-bit GPR flag
5416    let Inst{23-22} = 0b01; // 64-bit FPR flag
5417  }
5418
5419  def UXHri: BaseIntegerToFPUnscaled<rmode, opcode, GPR64, FPR16, f16, asm, node> {
5420    let Inst{31} = 1; // 64-bit GPR flag
5421    let Inst{23-22} = 0b11; // 16-bit FPR flag
5422    let Predicates = [HasFullFP16];
5423  }
5424
5425  def UXSri: BaseIntegerToFPUnscaled<rmode, opcode, GPR64, FPR32, f32, asm, node> {
5426    let Inst{31} = 1; // 64-bit GPR flag
5427    let Inst{23-22} = 0b00; // 32-bit FPR flag
5428  }
5429
5430  def UXDri: BaseIntegerToFPUnscaled<rmode, opcode, GPR64, FPR64, f64, asm, node> {
5431    let Inst{31} = 1; // 64-bit GPR flag
5432    let Inst{23-22} = 0b01; // 64-bit FPR flag
5433  }
5434
5435  // Scaled
5436  def SWHri: BaseIntegerToFP<rmode, opcode, GPR32, FPR16, fixedpoint_recip_f16_i32, asm,
5437                             [(set (f16 FPR16:$Rd),
5438                                   (fmul (node GPR32:$Rn),
5439                                         fixedpoint_recip_f16_i32:$scale))]> {
5440    let Inst{31} = 0; // 32-bit GPR flag
5441    let Inst{23-22} = 0b11; // 16-bit FPR flag
5442    let scale{5} = 1;
5443    let Predicates = [HasFullFP16];
5444  }
5445
5446  def SWSri: BaseIntegerToFP<rmode, opcode, GPR32, FPR32, fixedpoint_recip_f32_i32, asm,
5447                             [(set FPR32:$Rd,
5448                                   (fmul (node GPR32:$Rn),
5449                                         fixedpoint_recip_f32_i32:$scale))]> {
5450    let Inst{31} = 0; // 32-bit GPR flag
5451    let Inst{23-22} = 0b00; // 32-bit FPR flag
5452    let scale{5} = 1;
5453  }
5454
5455  def SWDri: BaseIntegerToFP<rmode, opcode, GPR32, FPR64, fixedpoint_recip_f64_i32, asm,
5456                             [(set FPR64:$Rd,
5457                                   (fmul (node GPR32:$Rn),
5458                                         fixedpoint_recip_f64_i32:$scale))]> {
5459    let Inst{31} = 0; // 32-bit GPR flag
5460    let Inst{23-22} = 0b01; // 64-bit FPR flag
5461    let scale{5} = 1;
5462  }
5463
5464  def SXHri: BaseIntegerToFP<rmode, opcode, GPR64, FPR16, fixedpoint_recip_f16_i64, asm,
5465                             [(set (f16 FPR16:$Rd),
5466                                   (fmul (node GPR64:$Rn),
5467                                         fixedpoint_recip_f16_i64:$scale))]> {
5468    let Inst{31} = 1; // 64-bit GPR flag
5469    let Inst{23-22} = 0b11; // 16-bit FPR flag
5470    let Predicates = [HasFullFP16];
5471  }
5472
5473  def SXSri: BaseIntegerToFP<rmode, opcode, GPR64, FPR32, fixedpoint_recip_f32_i64, asm,
5474                             [(set FPR32:$Rd,
5475                                   (fmul (node GPR64:$Rn),
5476                                         fixedpoint_recip_f32_i64:$scale))]> {
5477    let Inst{31} = 1; // 64-bit GPR flag
5478    let Inst{23-22} = 0b00; // 32-bit FPR flag
5479  }
5480
5481  def SXDri: BaseIntegerToFP<rmode, opcode, GPR64, FPR64, fixedpoint_recip_f64_i64, asm,
5482                             [(set FPR64:$Rd,
5483                                   (fmul (node GPR64:$Rn),
5484                                         fixedpoint_recip_f64_i64:$scale))]> {
5485    let Inst{31} = 1; // 64-bit GPR flag
5486    let Inst{23-22} = 0b01; // 64-bit FPR flag
5487  }
5488}
5489
5490multiclass IntegerToFPSIMDScalar<bits<2> rmode, bits<3> opcode, string asm, SDPatternOperator node = null_frag> {
5491  // 32-bit to half-precision
5492  def HSr: BaseIntegerToFPUnscaled<rmode, opcode, FPR32, FPR16, f16, asm, node> {
5493    let Inst{31} = 0; // 32-bit FPR flag
5494    let Inst{23-22} = 0b11; // 16-bit FPR flag
5495  }
5496
5497  // 32-bit to double-precision
5498  def DSr: BaseIntegerToFPUnscaled<rmode, opcode, FPR32, FPR64, f64, asm, node> {
5499    let Inst{31} = 0; // 32-bit FPR flag
5500    let Inst{23-22} = 0b01; // 64-bit FPR flag
5501  }
5502
5503  // 64-bit to half-precision
5504  def HDr: BaseIntegerToFPUnscaled<rmode, opcode, FPR64, FPR16, f16, asm, node> {
5505    let Inst{31} = 1; // 64-bit FPR flag
5506    let Inst{23-22} = 0b11; // 16-bit FPR flag
5507  }
5508
5509  // 64-bit to single-precision
5510  def SDr: BaseIntegerToFPUnscaled<rmode, opcode, FPR64, FPR32, f32, asm, node> {
5511    let Inst{31} = 1; // 64-bit FPR flag
5512    let Inst{23-22} = 0b00; // 32-bit FPR flag
5513  }
5514}
5515
5516//---
5517// Unscaled integer <-> floating point conversion (i.e. FMOV)
5518//---
5519
5520let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5521class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5522                      RegisterClass srcType, RegisterClass dstType,
5523                      string asm>
5524    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5525        // We use COPY_TO_REGCLASS for these bitconvert operations.
5526        // copyPhysReg() expands the resultant COPY instructions after
5527        // regalloc is done. This gives greater freedom for the allocator
5528        // and related passes (coalescing, copy propagation, et. al.) to
5529        // be more effective.
5530        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5531      Sched<[WriteFCopy]> {
5532  bits<5> Rd;
5533  bits<5> Rn;
5534  let Inst{30-24} = 0b0011110;
5535  let Inst{21}    = 1;
5536  let Inst{20-19} = rmode;
5537  let Inst{18-16} = opcode;
5538  let Inst{15-10} = 0b000000;
5539  let Inst{9-5}   = Rn;
5540  let Inst{4-0}   = Rd;
5541}
5542
5543let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5544class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5545                     RegisterClass srcType, RegisterOperand dstType, string asm,
5546                     string kind>
5547    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5548        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5549      Sched<[WriteFCopy]> {
5550  bits<5> Rd;
5551  bits<5> Rn;
5552  let Inst{30-23} = 0b00111101;
5553  let Inst{21}    = 1;
5554  let Inst{20-19} = rmode;
5555  let Inst{18-16} = opcode;
5556  let Inst{15-10} = 0b000000;
5557  let Inst{9-5}   = Rn;
5558  let Inst{4-0}   = Rd;
5559
5560  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5561}
5562
5563let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5564class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5565                     RegisterOperand srcType, RegisterClass dstType, string asm,
5566                     string kind>
5567    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5568        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5569      Sched<[WriteFCopy]> {
5570  bits<5> Rd;
5571  bits<5> Rn;
5572  let Inst{30-23} = 0b00111101;
5573  let Inst{21}    = 1;
5574  let Inst{20-19} = rmode;
5575  let Inst{18-16} = opcode;
5576  let Inst{15-10} = 0b000000;
5577  let Inst{9-5}   = Rn;
5578  let Inst{4-0}   = Rd;
5579
5580  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5581}
5582
5583
5584multiclass UnscaledConversion<string asm> {
5585  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5586    let Inst{31} = 0; // 32-bit GPR flag
5587    let Inst{23-22} = 0b11; // 16-bit FPR flag
5588    let Predicates = [HasFullFP16];
5589  }
5590
5591  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5592    let Inst{31} = 1; // 64-bit GPR flag
5593    let Inst{23-22} = 0b11; // 16-bit FPR flag
5594    let Predicates = [HasFullFP16];
5595  }
5596
5597  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5598    let Inst{31} = 0; // 32-bit GPR flag
5599    let Inst{23-22} = 0b00; // 32-bit FPR flag
5600  }
5601
5602  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5603    let Inst{31} = 1; // 64-bit GPR flag
5604    let Inst{23-22} = 0b01; // 64-bit FPR flag
5605  }
5606
5607  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5608    let Inst{31} = 0; // 32-bit GPR flag
5609    let Inst{23-22} = 0b11; // 16-bit FPR flag
5610    let Predicates = [HasFullFP16];
5611  }
5612
5613  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5614    let Inst{31} = 1; // 64-bit GPR flag
5615    let Inst{23-22} = 0b11; // 16-bit FPR flag
5616    let Predicates = [HasFullFP16];
5617  }
5618
5619  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5620    let Inst{31} = 0; // 32-bit GPR flag
5621    let Inst{23-22} = 0b00; // 32-bit FPR flag
5622  }
5623
5624  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5625    let Inst{31} = 1; // 64-bit GPR flag
5626    let Inst{23-22} = 0b01; // 64-bit FPR flag
5627  }
5628
5629  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5630                                             asm, ".d"> {
5631    let Inst{31} = 1;
5632    let Inst{22} = 0;
5633  }
5634
5635  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5636                                               asm, ".d"> {
5637    let Inst{31} = 1;
5638    let Inst{22} = 0;
5639  }
5640}
5641
5642//---
5643// Floating point conversion
5644//---
5645
5646let mayRaiseFPException = 1, Uses = [FPCR] in
5647class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5648                       RegisterClass srcType, string asm, list<dag> pattern>
5649    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5650      Sched<[WriteFCvt]> {
5651  bits<5> Rd;
5652  bits<5> Rn;
5653  let Inst{31-24} = 0b00011110;
5654  let Inst{23-22} = type;
5655  let Inst{21-17} = 0b10001;
5656  let Inst{16-15} = opcode;
5657  let Inst{14-10} = 0b10000;
5658  let Inst{9-5}   = Rn;
5659  let Inst{4-0}   = Rd;
5660}
5661
5662multiclass FPConversion<string asm> {
5663  // Double-precision to Half-precision
5664  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5665                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5666
5667  // Double-precision to Single-precision
5668  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5669                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5670
5671  // Half-precision to Double-precision
5672  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5673                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5674
5675  // Half-precision to Single-precision
5676  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5677                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5678
5679  // Single-precision to Double-precision
5680  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5681                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5682
5683  // Single-precision to Half-precision
5684  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5685                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5686}
5687
5688//---
5689// Single operand floating point data processing
5690//---
5691
5692let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5693class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5694                              ValueType vt, string asm, SDPatternOperator node>
5695    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5696         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5697      Sched<[WriteF]> {
5698  bits<5> Rd;
5699  bits<5> Rn;
5700  let Inst{31-24} = 0b00011110;
5701  let Inst{21}    = 0b1;
5702  let Inst{20-15} = opcode;
5703  let Inst{14-10} = 0b10000;
5704  let Inst{9-5}   = Rn;
5705  let Inst{4-0}   = Rd;
5706}
5707
5708multiclass SingleOperandFPData<bits<4> opcode, string asm,
5709                               SDPatternOperator node = null_frag,
5710                               int fpexceptions = 1> {
5711  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5712  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5713    let Inst{23-22} = 0b11; // 16-bit size flag
5714    let Predicates = [HasFullFP16];
5715  }
5716
5717  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5718    let Inst{23-22} = 0b00; // 32-bit size flag
5719  }
5720
5721  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5722    let Inst{23-22} = 0b01; // 64-bit size flag
5723  }
5724  }
5725}
5726
5727multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5728                                       SDPatternOperator node = null_frag>
5729    : SingleOperandFPData<opcode, asm, node, 0>;
5730
5731let mayRaiseFPException = 1, Uses = [FPCR] in
5732multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5733                  SDPatternOperator node = null_frag>{
5734
5735  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5736    let Inst{23-22} = 0b00; // 32-bit registers
5737  }
5738
5739  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5740    let Inst{23-22} = 0b01; // 64-bit registers
5741  }
5742}
5743
5744// FRInt[32|64][Z|N] instructions
5745multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5746      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5747
5748//---
5749// Two operand floating point data processing
5750//---
5751
5752let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5753class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5754                           string asm, list<dag> pat>
5755    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5756         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5757      Sched<[WriteF]> {
5758  bits<5> Rd;
5759  bits<5> Rn;
5760  bits<5> Rm;
5761  let Inst{31-24} = 0b00011110;
5762  let Inst{21}    = 1;
5763  let Inst{20-16} = Rm;
5764  let Inst{15-12} = opcode;
5765  let Inst{11-10} = 0b10;
5766  let Inst{9-5}   = Rn;
5767  let Inst{4-0}   = Rd;
5768}
5769
5770multiclass TwoOperandFPData<bits<4> opcode, string asm,
5771                            SDPatternOperator node = null_frag> {
5772  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5773                         [(set (f16 FPR16:$Rd),
5774                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5775    let Inst{23-22} = 0b11; // 16-bit size flag
5776    let Predicates = [HasFullFP16];
5777  }
5778
5779  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5780                         [(set (f32 FPR32:$Rd),
5781                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5782    let Inst{23-22} = 0b00; // 32-bit size flag
5783  }
5784
5785  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5786                         [(set (f64 FPR64:$Rd),
5787                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5788    let Inst{23-22} = 0b01; // 64-bit size flag
5789  }
5790}
5791
5792multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5793                               SDPatternOperator node> {
5794  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5795                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5796    let Inst{23-22} = 0b11; // 16-bit size flag
5797    let Predicates = [HasFullFP16];
5798  }
5799
5800  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5801                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5802    let Inst{23-22} = 0b00; // 32-bit size flag
5803  }
5804
5805  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5806                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5807    let Inst{23-22} = 0b01; // 64-bit size flag
5808  }
5809}
5810
5811
5812//---
5813// Three operand floating point data processing
5814//---
5815
5816let mayRaiseFPException = 1, Uses = [FPCR] in
5817class BaseThreeOperandFPData<bit isNegated, bit isSub,
5818                             RegisterClass regtype, string asm, list<dag> pat>
5819    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5820         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5821      Sched<[WriteFMul]> {
5822  bits<5> Rd;
5823  bits<5> Rn;
5824  bits<5> Rm;
5825  bits<5> Ra;
5826  let Inst{31-24} = 0b00011111;
5827  let Inst{21}    = isNegated;
5828  let Inst{20-16} = Rm;
5829  let Inst{15}    = isSub;
5830  let Inst{14-10} = Ra;
5831  let Inst{9-5}   = Rn;
5832  let Inst{4-0}   = Rd;
5833}
5834
5835multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5836                              SDPatternOperator node> {
5837  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5838            [(set (f16 FPR16:$Rd),
5839                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5840    let Inst{23-22} = 0b11; // 16-bit size flag
5841    let Predicates = [HasFullFP16];
5842  }
5843
5844  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5845            [(set FPR32:$Rd,
5846                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5847    let Inst{23-22} = 0b00; // 32-bit size flag
5848  }
5849
5850  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5851            [(set FPR64:$Rd,
5852                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5853    let Inst{23-22} = 0b01; // 64-bit size flag
5854  }
5855
5856  let Predicates = [HasFullFP16] in {
5857  def : Pat<(f16 (node (f16 FPR16:$Rn),
5858                       (f16 (extractelt (v8f16 V128:$Rm), (i64 0))),
5859                       (f16 FPR16:$Ra))),
5860            (!cast<Instruction>(NAME # Hrrr)
5861              FPR16:$Rn, (f16 (EXTRACT_SUBREG V128:$Rm, hsub)), FPR16:$Ra)>;
5862
5863  def : Pat<(f16 (node (f16 (extractelt (v8f16 V128:$Rn), (i64 0))),
5864                       (f16 FPR16:$Rm),
5865                       (f16 FPR16:$Ra))),
5866            (!cast<Instruction>(NAME # Hrrr)
5867              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), FPR16:$Rm, FPR16:$Ra)>;
5868
5869  def : Pat<(f16 (node (f16 (extractelt (v8f16 V128:$Rn), (i64 0))),
5870                       (f16 (extractelt (v8f16 V128:$Rm), (i64 0))),
5871                       (f16 FPR16:$Ra))),
5872            (!cast<Instruction>(NAME # Hrrr)
5873              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)),
5874              (f16 (EXTRACT_SUBREG V128:$Rm, hsub)), FPR16:$Ra)>;
5875  }
5876
5877  def : Pat<(f32 (node (f32 FPR32:$Rn),
5878                       (f32 (extractelt (v4f32 V128:$Rm), (i64 0))),
5879                       (f32 FPR32:$Ra))),
5880            (!cast<Instruction>(NAME # Srrr)
5881              FPR32:$Rn, (EXTRACT_SUBREG V128:$Rm, ssub), FPR32:$Ra)>;
5882
5883  def : Pat<(f32 (node (f32 (extractelt (v4f32 V128:$Rn), (i64 0))),
5884                       (f32 FPR32:$Rm),
5885                       (f32 FPR32:$Ra))),
5886            (!cast<Instruction>(NAME # Srrr)
5887              (EXTRACT_SUBREG V128:$Rn, ssub), FPR32:$Rm, FPR32:$Ra)>;
5888
5889  def : Pat<(f32 (node (f32 (extractelt (v4f32 V128:$Rn), (i64 0))),
5890                       (f32 (extractelt (v4f32 V128:$Rm), (i64 0))),
5891                       (f32 FPR32:$Ra))),
5892            (!cast<Instruction>(NAME # Srrr)
5893              (EXTRACT_SUBREG V128:$Rn, ssub),
5894              (EXTRACT_SUBREG V128:$Rm, ssub), FPR32:$Ra)>;
5895
5896  def : Pat<(f64 (node (f64 FPR64:$Rn),
5897                       (f64 (extractelt (v2f64 V128:$Rm), (i64 0))),
5898                       (f64 FPR64:$Ra))),
5899            (!cast<Instruction>(NAME # Drrr)
5900              FPR64:$Rn, (EXTRACT_SUBREG V128:$Rm, dsub), FPR64:$Ra)>;
5901
5902  def : Pat<(f64 (node (f64 (extractelt (v2f64 V128:$Rn), (i64 0))),
5903                       (f64 FPR64:$Rm),
5904                       (f64 FPR64:$Ra))),
5905            (!cast<Instruction>(NAME # Drrr)
5906              (EXTRACT_SUBREG V128:$Rn, dsub), FPR64:$Rm, FPR64:$Ra)>;
5907
5908  def : Pat<(f64 (node (f64 (extractelt (v2f64 V128:$Rn), (i64 0))),
5909                       (f64 (extractelt (v2f64 V128:$Rm), (i64 0))),
5910                       (f64 FPR64:$Ra))),
5911            (!cast<Instruction>(NAME # Drrr)
5912              (EXTRACT_SUBREG V128:$Rn, dsub),
5913              (EXTRACT_SUBREG V128:$Rm, dsub), FPR64:$Ra)>;
5914}
5915
5916//---
5917// Floating point data comparisons
5918//---
5919
5920let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5921class BaseOneOperandFPComparison<bit signalAllNans,
5922                                 RegisterClass regtype, string asm,
5923                                 list<dag> pat>
5924    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5925      Sched<[WriteFCmp]> {
5926  bits<5> Rn;
5927  let Inst{31-24} = 0b00011110;
5928  let Inst{21}    = 1;
5929
5930  let Inst{15-10} = 0b001000;
5931  let Inst{9-5}   = Rn;
5932  let Inst{4}     = signalAllNans;
5933  let Inst{3-0}   = 0b1000;
5934
5935  // Rm should be 0b00000 canonically, but we need to accept any value.
5936  let PostEncoderMethod = "fixOneOperandFPComparison";
5937}
5938
5939let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5940class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5941                                string asm, list<dag> pat>
5942    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5943      Sched<[WriteFCmp]> {
5944  bits<5> Rm;
5945  bits<5> Rn;
5946  let Inst{31-24} = 0b00011110;
5947  let Inst{21}    = 1;
5948  let Inst{20-16} = Rm;
5949  let Inst{15-10} = 0b001000;
5950  let Inst{9-5}   = Rn;
5951  let Inst{4}     = signalAllNans;
5952  let Inst{3-0}   = 0b0000;
5953}
5954
5955multiclass FPComparison<bit signalAllNans, string asm,
5956                        SDPatternOperator OpNode = null_frag> {
5957  let Defs = [NZCV] in {
5958  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5959      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5960    let Inst{23-22} = 0b11;
5961    let Predicates = [HasFullFP16];
5962  }
5963
5964  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5965      [(set NZCV, (OpNode (f16 FPR16:$Rn), fpimm0))]> {
5966    let Inst{23-22} = 0b11;
5967    let Predicates = [HasFullFP16];
5968  }
5969
5970  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5971      [(set NZCV, (OpNode FPR32:$Rn, (f32 FPR32:$Rm)))]> {
5972    let Inst{23-22} = 0b00;
5973  }
5974
5975  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5976      [(set NZCV, (OpNode (f32 FPR32:$Rn), fpimm0))]> {
5977    let Inst{23-22} = 0b00;
5978  }
5979
5980  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5981      [(set NZCV, (OpNode FPR64:$Rn, (f64 FPR64:$Rm)))]> {
5982    let Inst{23-22} = 0b01;
5983  }
5984
5985  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5986      [(set NZCV, (OpNode (f64 FPR64:$Rn), fpimm0))]> {
5987    let Inst{23-22} = 0b01;
5988  }
5989  } // Defs = [NZCV]
5990}
5991
5992//---
5993// Floating point conditional comparisons
5994//---
5995
5996let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5997class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5998                           string mnemonic, list<dag> pat>
5999    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
6000         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
6001      Sched<[WriteFCmp]> {
6002  let Uses = [NZCV];
6003  let Defs = [NZCV];
6004
6005  bits<5> Rn;
6006  bits<5> Rm;
6007  bits<4> nzcv;
6008  bits<4> cond;
6009
6010  let Inst{31-24} = 0b00011110;
6011  let Inst{21}    = 1;
6012  let Inst{20-16} = Rm;
6013  let Inst{15-12} = cond;
6014  let Inst{11-10} = 0b01;
6015  let Inst{9-5}   = Rn;
6016  let Inst{4}     = signalAllNans;
6017  let Inst{3-0}   = nzcv;
6018}
6019
6020multiclass FPCondComparison<bit signalAllNans, string mnemonic,
6021                            SDPatternOperator OpNode = null_frag> {
6022  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
6023      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
6024                          (i32 imm:$cond), NZCV))]> {
6025    let Inst{23-22} = 0b11;
6026    let Predicates = [HasFullFP16];
6027  }
6028
6029  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
6030      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
6031                          (i32 imm:$cond), NZCV))]> {
6032    let Inst{23-22} = 0b00;
6033  }
6034
6035  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
6036      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
6037                          (i32 imm:$cond), NZCV))]> {
6038    let Inst{23-22} = 0b01;
6039  }
6040}
6041
6042//---
6043// Floating point conditional select
6044//---
6045
6046class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
6047    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
6048         asm, "\t$Rd, $Rn, $Rm, $cond", "",
6049         [(set regtype:$Rd,
6050               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
6051                          (i32 imm:$cond), NZCV))]>,
6052      Sched<[WriteF]> {
6053  bits<5> Rd;
6054  bits<5> Rn;
6055  bits<5> Rm;
6056  bits<4> cond;
6057
6058  let Inst{31-24} = 0b00011110;
6059  let Inst{21}    = 1;
6060  let Inst{20-16} = Rm;
6061  let Inst{15-12} = cond;
6062  let Inst{11-10} = 0b11;
6063  let Inst{9-5}   = Rn;
6064  let Inst{4-0}   = Rd;
6065}
6066
6067multiclass FPCondSelect<string asm> {
6068  let Uses = [NZCV] in {
6069  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
6070    let Inst{23-22} = 0b11;
6071    let Predicates = [HasFullFP16];
6072  }
6073
6074  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
6075    let Inst{23-22} = 0b00;
6076  }
6077
6078  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
6079    let Inst{23-22} = 0b01;
6080  }
6081  } // Uses = [NZCV]
6082}
6083
6084//---
6085// Floating move immediate
6086//---
6087
6088class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
6089  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
6090      [(set regtype:$Rd, fpimmtype:$imm)]>,
6091    Sched<[WriteFImm]> {
6092  bits<5> Rd;
6093  bits<8> imm;
6094  let Inst{31-24} = 0b00011110;
6095  let Inst{21}    = 1;
6096  let Inst{20-13} = imm;
6097  let Inst{12-5}  = 0b10000000;
6098  let Inst{4-0}   = Rd;
6099}
6100
6101multiclass FPMoveImmediate<string asm> {
6102  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
6103    let Inst{23-22} = 0b11;
6104    let Predicates = [HasFullFP16];
6105  }
6106
6107  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
6108    let Inst{23-22} = 0b00;
6109  }
6110
6111  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
6112    let Inst{23-22} = 0b01;
6113  }
6114}
6115} // end of 'let Predicates = [HasFPARMv8]'
6116
6117//----------------------------------------------------------------------------
6118// AdvSIMD
6119//----------------------------------------------------------------------------
6120
6121let Predicates = [HasNEON] in {
6122
6123//----------------------------------------------------------------------------
6124// AdvSIMD three register vector instructions
6125//----------------------------------------------------------------------------
6126
6127let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6128class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
6129                        RegisterOperand regtype, string asm, string kind,
6130                        list<dag> pattern>
6131  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6132      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6133      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
6134    Sched<[!if(Q, WriteVq, WriteVd)]> {
6135  bits<5> Rd;
6136  bits<5> Rn;
6137  bits<5> Rm;
6138  let Inst{31}    = 0;
6139  let Inst{30}    = Q;
6140  let Inst{29}    = U;
6141  let Inst{28-24} = 0b01110;
6142  let Inst{23-21} = size;
6143  let Inst{20-16} = Rm;
6144  let Inst{15-11} = opcode;
6145  let Inst{10}    = 1;
6146  let Inst{9-5}   = Rn;
6147  let Inst{4-0}   = Rd;
6148}
6149
6150let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6151class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
6152                        RegisterOperand regtype, string asm, string kind,
6153                        list<dag> pattern>
6154  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
6155      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6156      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6157    Sched<[!if(Q, WriteVq, WriteVd)]> {
6158  bits<5> Rd;
6159  bits<5> Rn;
6160  bits<5> Rm;
6161  let Inst{31}    = 0;
6162  let Inst{30}    = Q;
6163  let Inst{29}    = U;
6164  let Inst{28-24} = 0b01110;
6165  let Inst{23-21} = size;
6166  let Inst{20-16} = Rm;
6167  let Inst{15-11} = opcode;
6168  let Inst{10}    = 1;
6169  let Inst{9-5}   = Rn;
6170  let Inst{4-0}   = Rd;
6171}
6172
6173let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6174class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
6175  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
6176    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
6177
6178multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
6179  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
6180             [(set (v8i8 V64:$dst),
6181                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6182  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
6183             [(set (v16i8 V128:$dst),
6184                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
6185                           (v16i8 V128:$Rm)))]>;
6186
6187  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
6188                           (v4i16 V64:$RHS))),
6189          (!cast<Instruction>(NAME#"v8i8")
6190            V64:$LHS, V64:$MHS, V64:$RHS)>;
6191  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
6192                           (v2i32 V64:$RHS))),
6193          (!cast<Instruction>(NAME#"v8i8")
6194            V64:$LHS, V64:$MHS, V64:$RHS)>;
6195  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
6196                           (v1i64 V64:$RHS))),
6197          (!cast<Instruction>(NAME#"v8i8")
6198            V64:$LHS, V64:$MHS, V64:$RHS)>;
6199
6200  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
6201                           (v8i16 V128:$RHS))),
6202      (!cast<Instruction>(NAME#"v16i8")
6203        V128:$LHS, V128:$MHS, V128:$RHS)>;
6204  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
6205                           (v4i32 V128:$RHS))),
6206      (!cast<Instruction>(NAME#"v16i8")
6207        V128:$LHS, V128:$MHS, V128:$RHS)>;
6208  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
6209                           (v2i64 V128:$RHS))),
6210      (!cast<Instruction>(NAME#"v16i8")
6211        V128:$LHS, V128:$MHS, V128:$RHS)>;
6212}
6213
6214// All operand sizes distinguished in the encoding.
6215multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
6216                               SDPatternOperator OpNode> {
6217  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
6218                                      asm, ".8b",
6219         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6220  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
6221                                      asm, ".16b",
6222         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
6223  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
6224                                      asm, ".4h",
6225         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6226  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
6227                                      asm, ".8h",
6228         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6229  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
6230                                      asm, ".2s",
6231         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6232  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
6233                                      asm, ".4s",
6234         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6235  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
6236                                      asm, ".2d",
6237         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6238}
6239
6240multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
6241  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
6242          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
6243  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
6244          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
6245  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
6246          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
6247
6248  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
6249          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
6250  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
6251          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
6252  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
6253          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
6254  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
6255          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
6256}
6257
6258// As above, but D sized elements unsupported.
6259multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
6260                                  SDPatternOperator OpNode> {
6261  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
6262                                      asm, ".8b",
6263        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
6264  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
6265                                      asm, ".16b",
6266        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
6267  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
6268                                      asm, ".4h",
6269        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
6270  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
6271                                      asm, ".8h",
6272        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
6273  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
6274                                      asm, ".2s",
6275        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
6276  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
6277                                      asm, ".4s",
6278        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
6279}
6280
6281multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
6282                                  SDPatternOperator OpNode> {
6283  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
6284                                      asm, ".8b",
6285      [(set (v8i8 V64:$dst),
6286            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6287  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
6288                                      asm, ".16b",
6289      [(set (v16i8 V128:$dst),
6290            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
6291  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
6292                                      asm, ".4h",
6293      [(set (v4i16 V64:$dst),
6294            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6295  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
6296                                      asm, ".8h",
6297      [(set (v8i16 V128:$dst),
6298            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6299  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
6300                                      asm, ".2s",
6301      [(set (v2i32 V64:$dst),
6302            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6303  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
6304                                      asm, ".4s",
6305      [(set (v4i32 V128:$dst),
6306            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6307}
6308
6309// As above, but only B sized elements supported.
6310multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
6311                                SDPatternOperator OpNode> {
6312  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
6313                                      asm, ".8b",
6314    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6315  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
6316                                      asm, ".16b",
6317    [(set (v16i8 V128:$Rd),
6318          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
6319}
6320
6321// As above, but only floating point elements supported.
6322let mayRaiseFPException = 1, Uses = [FPCR] in
6323multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
6324                                 string asm, SDPatternOperator OpNode> {
6325  let Predicates = [HasNEON, HasFullFP16] in {
6326  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
6327                                      asm, ".4h",
6328        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
6329  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
6330                                      asm, ".8h",
6331        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
6332  } // Predicates = [HasNEON, HasFullFP16]
6333  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
6334                                      asm, ".2s",
6335        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6336  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
6337                                      asm, ".4s",
6338        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6339  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
6340                                      asm, ".2d",
6341        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6342}
6343
6344let mayRaiseFPException = 1, Uses = [FPCR] in
6345multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
6346                                    string asm,
6347                                    SDPatternOperator OpNode> {
6348  let Predicates = [HasNEON, HasFullFP16] in {
6349  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
6350                                      asm, ".4h",
6351        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
6352  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
6353                                      asm, ".8h",
6354        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
6355  } // Predicates = [HasNEON, HasFullFP16]
6356  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
6357                                      asm, ".2s",
6358        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6359  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
6360                                      asm, ".4s",
6361        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6362  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
6363                                      asm, ".2d",
6364        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6365}
6366
6367let mayRaiseFPException = 1, Uses = [FPCR] in
6368multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
6369                                 string asm, SDPatternOperator OpNode> {
6370  let Predicates = [HasNEON, HasFullFP16] in {
6371  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
6372                                      asm, ".4h",
6373     [(set (v4f16 V64:$dst),
6374           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
6375  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
6376                                      asm, ".8h",
6377     [(set (v8f16 V128:$dst),
6378           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
6379  } // Predicates = [HasNEON, HasFullFP16]
6380  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
6381                                      asm, ".2s",
6382     [(set (v2f32 V64:$dst),
6383           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6384  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
6385                                      asm, ".4s",
6386     [(set (v4f32 V128:$dst),
6387           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6388  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
6389                                      asm, ".2d",
6390     [(set (v2f64 V128:$dst),
6391           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6392}
6393
6394// As above, but D and B sized elements unsupported.
6395let mayRaiseFPException = 1, Uses = [FPCR] in
6396multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
6397                                SDPatternOperator OpNode> {
6398  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
6399                                      asm, ".4h",
6400        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6401  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
6402                                      asm, ".8h",
6403        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6404  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
6405                                      asm, ".2s",
6406        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6407  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
6408                                      asm, ".4s",
6409        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6410}
6411
6412// Logical three vector ops share opcode bits, and only use B sized elements.
6413multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
6414                                  SDPatternOperator OpNode = null_frag> {
6415  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
6416                                     asm, ".8b",
6417                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
6418  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
6419                                     asm, ".16b",
6420                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
6421
6422  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
6423          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6424  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
6425          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6426  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
6427          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6428
6429  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
6430      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6431  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
6432      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6433  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
6434      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6435}
6436
6437multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
6438                                  string asm, SDPatternOperator OpNode = null_frag> {
6439  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
6440                                     asm, ".8b",
6441             [(set (v8i8 V64:$dst),
6442                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6443  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
6444                                     asm, ".16b",
6445             [(set (v16i8 V128:$dst),
6446                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
6447                           (v16i8 V128:$Rm)))]>;
6448
6449  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
6450                           (v4i16 V64:$RHS))),
6451          (!cast<Instruction>(NAME#"v8i8")
6452            V64:$LHS, V64:$MHS, V64:$RHS)>;
6453  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
6454                           (v2i32 V64:$RHS))),
6455          (!cast<Instruction>(NAME#"v8i8")
6456            V64:$LHS, V64:$MHS, V64:$RHS)>;
6457  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
6458                           (v1i64 V64:$RHS))),
6459          (!cast<Instruction>(NAME#"v8i8")
6460            V64:$LHS, V64:$MHS, V64:$RHS)>;
6461
6462  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
6463                           (v8i16 V128:$RHS))),
6464      (!cast<Instruction>(NAME#"v16i8")
6465        V128:$LHS, V128:$MHS, V128:$RHS)>;
6466  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
6467                           (v4i32 V128:$RHS))),
6468      (!cast<Instruction>(NAME#"v16i8")
6469        V128:$LHS, V128:$MHS, V128:$RHS)>;
6470  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
6471                           (v2i64 V128:$RHS))),
6472      (!cast<Instruction>(NAME#"v16i8")
6473        V128:$LHS, V128:$MHS, V128:$RHS)>;
6474}
6475
6476// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
6477// bytes from S-sized elements.
6478class BaseSIMDThreeSameVectorDot<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
6479                                 string kind1, string kind2, RegisterOperand RegType,
6480                                 ValueType AccumType, ValueType InputType,
6481                                 SDPatternOperator OpNode> :
6482        BaseSIMDThreeSameVectorTied<Q, U, {sz, 0b0}, {0b1, opc}, RegType, asm, kind1,
6483        [(set (AccumType RegType:$dst),
6484              (OpNode (AccumType RegType:$Rd),
6485                      (InputType RegType:$Rn),
6486                      (InputType RegType:$Rm)))]> {
6487  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6488}
6489
6490multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
6491  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, 0b10, {0b001, Mixed}, asm, ".2s", ".8b", V64,
6492                                         v2i32, v8i8, OpNode>;
6493  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, 0b10, {0b001, Mixed}, asm, ".4s", ".16b", V128,
6494                                         v4i32, v16i8, OpNode>;
6495}
6496
6497// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
6498// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
6499// 8H to 4S, when Q=1).
6500let mayRaiseFPException = 1, Uses = [FPCR] in
6501class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
6502                                 string kind2, RegisterOperand RegType,
6503                                 ValueType AccumType, ValueType InputType,
6504                                 SDPatternOperator OpNode> :
6505        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
6506		[(set (AccumType RegType:$dst),
6507              (OpNode (AccumType RegType:$Rd),
6508                      (InputType RegType:$Rn),
6509                      (InputType RegType:$Rm)))]> {
6510  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6511  let Inst{13} = b13;
6512}
6513
6514multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
6515                                  SDPatternOperator OpNode> {
6516  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
6517                                         v2f32, v4f16, OpNode>;
6518  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
6519                                         v4f32, v8f16, OpNode>;
6520}
6521
6522multiclass SIMDThreeSameVectorMLA<bit Q, string asm, SDPatternOperator op> {
6523
6524  def v8f16 : BaseSIMDThreeSameVectorDot<Q, 0b0, 0b11, 0b1111, asm, ".8h", ".16b",
6525                                         V128, v8f16, v16i8, op>;
6526}
6527
6528multiclass SIMDThreeSameVectorMLAL<bit Q, bits<2> sz, string asm, SDPatternOperator op> {
6529  def v4f32 : BaseSIMDThreeSameVectorDot<Q, 0b0, sz, 0b1000, asm, ".4s", ".16b",
6530                                         V128, v4f32, v16i8, op>;
6531}
6532
6533// FP8 assembly/disassembly classes
6534
6535//----------------------------------------------------------------------------
6536// FP8 Advanced SIMD three-register extension
6537//----------------------------------------------------------------------------
6538class BaseSIMDThreeVectors<bit Q, bit U, bits<2> size, bits<4> op,
6539                           RegisterOperand regtype1,
6540                           RegisterOperand regtype2, string asm,
6541                           string kind1, string kind2>
6542  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, regtype2:$Rm), asm,
6543      "\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2, "", []>, Sched<[]> {
6544  bits<5> Rd;
6545  bits<5> Rn;
6546  bits<5> Rm;
6547  let Inst{31}    = 0;
6548  let Inst{30}    = Q;
6549  let Inst{29}    = U;
6550  let Inst{28-24} = 0b01110;
6551  let Inst{23-22} = size;
6552  let Inst{21}    = 0b0;
6553  let Inst{20-16} = Rm;
6554  let Inst{15}    = 0b1;
6555  let Inst{14-11} = op;
6556  let Inst{10}    = 0b1;
6557  let Inst{9-5}   = Rn;
6558  let Inst{4-0}   = Rd;
6559}
6560
6561
6562// FCVTN (FP16 to FP8)
6563multiclass SIMD_FP8_CVTN_F16<string asm, SDPatternOperator Op> {
6564  let Uses = [FPMR, FPCR], mayLoad = 1 in {
6565    def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b01, 0b1110, V64, V64, asm, ".8b",".4h">;
6566    def v16f8 : BaseSIMDThreeVectors<0b1, 0b0, 0b01, 0b1110,  V128, V128, asm, ".16b", ".8h">;
6567  }
6568  def : Pat<(v8i8 (Op (v4f16 V64:$Rn), (v4f16 V64:$Rm))),
6569            (!cast<Instruction>(NAME # v8f8) V64:$Rn, V64:$Rm)>;
6570  def : Pat<(v16i8 (Op (v8f16 V128:$Rn), (v8f16 V128:$Rm))),
6571            (!cast<Instruction>(NAME # v16f8) V128:$Rn, V128:$Rm)>;
6572}
6573
6574// FCVTN, FCVTN2 (FP32 to FP8)
6575multiclass SIMD_FP8_CVTN_F32<string asm, SDPatternOperator Op> {
6576  let Uses = [FPMR, FPCR], mayLoad = 1 in {
6577    def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b00, 0b1110, V64, V128, asm, ".8b", ".4s">;
6578    def 2v16f8 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1110, asm#2, ".16b", ".4s",
6579                                            V128, v16i8, v4f32, null_frag>;
6580  }
6581
6582  def : Pat<(v8i8 (Op (v4f32 V128:$Rn), (v4f32 V128:$Rm))),
6583            (!cast<Instruction>(NAME # v8f8) V128:$Rn, V128:$Rm)>;
6584
6585  def : Pat<(v16i8 (!cast<SDPatternOperator>(Op # 2) (v16i8 V128:$_Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm))),
6586            (!cast<Instruction>(NAME # 2v16f8) V128:$_Rd, V128:$Rn, V128:$Rm)>;
6587}
6588
6589multiclass SIMD_FP8_Dot2<string asm, SDPatternOperator op> {
6590  let Uses = [FPMR, FPCR], mayLoad = 1 in {
6591    def v4f16 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b01, 0b1111, asm, ".4h", ".8b",
6592                                           V64, v4f16, v8i8, op>;
6593    def v8f16 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b01, 0b1111, asm, ".8h", ".16b",
6594                                           V128, v8f16, v16i8, op>;
6595  }
6596}
6597
6598multiclass SIMD_FP8_Dot4<string asm, SDPatternOperator op> {
6599  let Uses = [FPMR, FPCR], mayLoad = 1 in {
6600    def v2f32 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b00, 0b1111, asm, ".2s", ".8b",
6601                                           V64, v2f32, v8i8, op>;
6602    def v4f32 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1111, asm, ".4s", ".16b",
6603                                           V128, v4f32, v16i8, op>;
6604  }
6605}
6606
6607let mayRaiseFPException = 1, Uses = [FPCR] in
6608multiclass SIMDThreeVectorFscale<bit U, bit S, bits<3> opc,
6609                                 string asm, SDPatternOperator OpNode> {
6610  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
6611                                      asm, ".4h",
6612        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6613  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
6614                                      asm, ".8h",
6615        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6616  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
6617                                      asm, ".2s",
6618        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6619  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
6620                                      asm, ".4s",
6621        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6622  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
6623                                      asm, ".2d",
6624        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6625}
6626
6627//----------------------------------------------------------------------------
6628// AdvSIMD two register vector instructions.
6629//----------------------------------------------------------------------------
6630
6631let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6632class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6633                            bits<2> size2, RegisterOperand regtype, string asm,
6634                            string dstkind, string srckind, list<dag> pattern>
6635  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6636      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6637      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
6638    Sched<[!if(Q, WriteVq, WriteVd)]> {
6639  bits<5> Rd;
6640  bits<5> Rn;
6641  let Inst{31}    = 0;
6642  let Inst{30}    = Q;
6643  let Inst{29}    = U;
6644  let Inst{28-24} = 0b01110;
6645  let Inst{23-22} = size;
6646  let Inst{21} = 0b1;
6647  let Inst{20-19} = size2;
6648  let Inst{18-17} = 0b00;
6649  let Inst{16-12} = opcode;
6650  let Inst{11-10} = 0b10;
6651  let Inst{9-5}   = Rn;
6652  let Inst{4-0}   = Rd;
6653}
6654
6655let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6656class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6657                                bits<2> size2, RegisterOperand regtype,
6658                                string asm, string dstkind, string srckind,
6659                                list<dag> pattern>
6660  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
6661      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6662      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6663    Sched<[!if(Q, WriteVq, WriteVd)]> {
6664  bits<5> Rd;
6665  bits<5> Rn;
6666  let Inst{31}    = 0;
6667  let Inst{30}    = Q;
6668  let Inst{29}    = U;
6669  let Inst{28-24} = 0b01110;
6670  let Inst{23-22} = size;
6671  let Inst{21} = 0b1;
6672  let Inst{20-19} = size2;
6673  let Inst{18-17} = 0b00;
6674  let Inst{16-12} = opcode;
6675  let Inst{11-10} = 0b10;
6676  let Inst{9-5}   = Rn;
6677  let Inst{4-0}   = Rd;
6678}
6679
6680// Supports B, H, and S element sizes.
6681multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
6682                            SDPatternOperator OpNode> {
6683  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6684                                      asm, ".8b", ".8b",
6685                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6686  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6687                                      asm, ".16b", ".16b",
6688                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6689  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6690                                      asm, ".4h", ".4h",
6691                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6692  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6693                                      asm, ".8h", ".8h",
6694                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6695  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6696                                      asm, ".2s", ".2s",
6697                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6698  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6699                                      asm, ".4s", ".4s",
6700                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6701}
6702
6703class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6704                            RegisterOperand regtype, string asm, string dstkind,
6705                            string srckind, string amount>
6706  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6707      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6708      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6709    Sched<[WriteVq]> {
6710  bits<5> Rd;
6711  bits<5> Rn;
6712  let Inst{31}    = 0;
6713  let Inst{30}    = Q;
6714  let Inst{29-24} = 0b101110;
6715  let Inst{23-22} = size;
6716  let Inst{21-10} = 0b100001001110;
6717  let Inst{9-5}   = Rn;
6718  let Inst{4-0}   = Rd;
6719}
6720
6721multiclass SIMDVectorLShiftLongBySizeBHS {
6722  let hasSideEffects = 0 in {
6723  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6724                                             "shll", ".8h",  ".8b", "8">;
6725  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6726                                             "shll2", ".8h", ".16b", "8">;
6727  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6728                                             "shll", ".4s",  ".4h", "16">;
6729  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6730                                             "shll2", ".4s", ".8h", "16">;
6731  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6732                                             "shll", ".2d",  ".2s", "32">;
6733  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6734                                             "shll2", ".2d", ".4s", "32">;
6735  }
6736}
6737
6738// Supports all element sizes.
6739multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6740                             SDPatternOperator OpNode> {
6741  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6742                                      asm, ".4h", ".8b",
6743               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6744  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6745                                      asm, ".8h", ".16b",
6746               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6747  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6748                                      asm, ".2s", ".4h",
6749               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6750  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6751                                      asm, ".4s", ".8h",
6752               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6753  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6754                                      asm, ".1d", ".2s",
6755               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6756  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6757                                      asm, ".2d", ".4s",
6758               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6759}
6760
6761multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6762                                 SDPatternOperator OpNode> {
6763  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6764                                          asm, ".4h", ".8b",
6765      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6766                                      (v8i8 V64:$Rn)))]>;
6767  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6768                                          asm, ".8h", ".16b",
6769      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6770                                      (v16i8 V128:$Rn)))]>;
6771  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6772                                          asm, ".2s", ".4h",
6773      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6774                                      (v4i16 V64:$Rn)))]>;
6775  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6776                                          asm, ".4s", ".8h",
6777      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6778                                      (v8i16 V128:$Rn)))]>;
6779  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6780                                          asm, ".1d", ".2s",
6781      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6782                                      (v2i32 V64:$Rn)))]>;
6783  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6784                                          asm, ".2d", ".4s",
6785      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6786                                      (v4i32 V128:$Rn)))]>;
6787}
6788
6789// Supports all element sizes, except 1xD.
6790multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6791                                  SDPatternOperator OpNode> {
6792  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6793                                    asm, ".8b", ".8b",
6794    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6795  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6796                                    asm, ".16b", ".16b",
6797    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6798  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6799                                    asm, ".4h", ".4h",
6800    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6801  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6802                                    asm, ".8h", ".8h",
6803    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6804  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6805                                    asm, ".2s", ".2s",
6806    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6807  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6808                                    asm, ".4s", ".4s",
6809    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6810  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6811                                    asm, ".2d", ".2d",
6812    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6813}
6814
6815multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6816                             SDPatternOperator OpNode = null_frag> {
6817  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6818                                asm, ".8b", ".8b",
6819    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6820  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6821                                asm, ".16b", ".16b",
6822    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6823  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6824                                asm, ".4h", ".4h",
6825    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6826  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6827                                asm, ".8h", ".8h",
6828    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6829  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6830                                asm, ".2s", ".2s",
6831    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6832  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6833                                asm, ".4s", ".4s",
6834    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6835  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6836                                asm, ".2d", ".2d",
6837    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6838}
6839
6840
6841// Supports only B element sizes.
6842multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6843                          SDPatternOperator OpNode> {
6844  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6845                                asm, ".8b", ".8b",
6846                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6847  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6848                                asm, ".16b", ".16b",
6849                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6850
6851}
6852
6853// Supports only B and H element sizes.
6854multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6855                                SDPatternOperator OpNode> {
6856  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6857                                asm, ".8b", ".8b",
6858                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6859  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6860                                asm, ".16b", ".16b",
6861                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6862  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6863                                asm, ".4h", ".4h",
6864                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6865  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6866                                asm, ".8h", ".8h",
6867                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6868}
6869
6870// Supports H, S and D element sizes, uses high bit of the size field
6871// as an extra opcode bit.
6872multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6873                           SDPatternOperator OpNode,
6874                           int fpexceptions = 1> {
6875  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6876  let Predicates = [HasNEON, HasFullFP16] in {
6877  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6878                                asm, ".4h", ".4h",
6879                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6880  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6881                                asm, ".8h", ".8h",
6882                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6883  } // Predicates = [HasNEON, HasFullFP16]
6884  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6885                                asm, ".2s", ".2s",
6886                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6887  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6888                                asm, ".4s", ".4s",
6889                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6890  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6891                                asm, ".2d", ".2d",
6892                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6893  }
6894}
6895
6896multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6897                                      SDPatternOperator OpNode>
6898    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6899
6900// Supports only S and D element sizes
6901let mayRaiseFPException = 1, Uses = [FPCR] in
6902multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6903                           SDPatternOperator OpNode = null_frag> {
6904
6905  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6906                                asm, ".2s", ".2s",
6907                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6908  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6909                                asm, ".4s", ".4s",
6910                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6911  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6912                                asm, ".2d", ".2d",
6913                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6914}
6915
6916multiclass FRIntNNTVector<bit U, bit op, string asm,
6917                          SDPatternOperator OpNode = null_frag> :
6918           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6919
6920// Supports only S element size.
6921multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6922                           SDPatternOperator OpNode> {
6923  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6924                                asm, ".2s", ".2s",
6925                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6926  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6927                                asm, ".4s", ".4s",
6928                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6929}
6930
6931let mayRaiseFPException = 1, Uses = [FPCR] in
6932multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6933                           SDPatternOperator OpNode> {
6934  let Predicates = [HasNEON, HasFullFP16] in {
6935  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6936                                asm, ".4h", ".4h",
6937                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6938  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6939                                asm, ".8h", ".8h",
6940                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6941  } // Predicates = [HasNEON, HasFullFP16]
6942  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6943                                asm, ".2s", ".2s",
6944                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6945  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6946                                asm, ".4s", ".4s",
6947                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6948  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6949                                asm, ".2d", ".2d",
6950                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6951}
6952
6953let mayRaiseFPException = 1, Uses = [FPCR] in
6954multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6955                           SDPatternOperator OpNode> {
6956  let Predicates = [HasNEON, HasFullFP16] in {
6957  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6958                                asm, ".4h", ".4h",
6959                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6960  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6961                                asm, ".8h", ".8h",
6962                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6963  } // Predicates = [HasNEON, HasFullFP16]
6964  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6965                                asm, ".2s", ".2s",
6966                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6967  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6968                                asm, ".4s", ".4s",
6969                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6970  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6971                                asm, ".2d", ".2d",
6972                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6973}
6974
6975let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6976class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6977                           RegisterOperand inreg, RegisterOperand outreg,
6978                           string asm, string outkind, string inkind,
6979                           list<dag> pattern>
6980  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6981      "{\t$Rd" # outkind # ", $Rn" # inkind #
6982      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6983    Sched<[WriteVq]> {
6984  bits<5> Rd;
6985  bits<5> Rn;
6986  let Inst{31}    = 0;
6987  let Inst{30}    = Q;
6988  let Inst{29}    = U;
6989  let Inst{28-24} = 0b01110;
6990  let Inst{23-22} = size;
6991  let Inst{21-17} = 0b10000;
6992  let Inst{16-12} = opcode;
6993  let Inst{11-10} = 0b10;
6994  let Inst{9-5}   = Rn;
6995  let Inst{4-0}   = Rd;
6996}
6997
6998let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6999class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
7000                           RegisterOperand inreg, RegisterOperand outreg,
7001                           string asm, string outkind, string inkind,
7002                           list<dag> pattern>
7003  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
7004      "{\t$Rd" # outkind # ", $Rn" # inkind #
7005      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
7006    Sched<[WriteVq]> {
7007  bits<5> Rd;
7008  bits<5> Rn;
7009  let Inst{31}    = 0;
7010  let Inst{30}    = Q;
7011  let Inst{29}    = U;
7012  let Inst{28-24} = 0b01110;
7013  let Inst{23-22} = size;
7014  let Inst{21-17} = 0b10000;
7015  let Inst{16-12} = opcode;
7016  let Inst{11-10} = 0b10;
7017  let Inst{9-5}   = Rn;
7018  let Inst{4-0}   = Rd;
7019}
7020
7021multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
7022                              SDPatternOperator OpNode> {
7023  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
7024                                      asm, ".8b", ".8h",
7025        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
7026  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
7027                                      asm#"2", ".16b", ".8h", []>;
7028  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
7029                                      asm, ".4h", ".4s",
7030        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
7031  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
7032                                      asm#"2", ".8h", ".4s", []>;
7033  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
7034                                      asm, ".2s", ".2d",
7035        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
7036  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
7037                                      asm#"2", ".4s", ".2d", []>;
7038
7039  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
7040            (!cast<Instruction>(NAME # "v16i8")
7041                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
7042  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
7043            (!cast<Instruction>(NAME # "v8i16")
7044                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
7045  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
7046            (!cast<Instruction>(NAME # "v4i32")
7047                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
7048}
7049
7050//----------------------------------------------------------------------------
7051// FP8 Advanced SIMD two-register miscellaneous
7052//----------------------------------------------------------------------------
7053multiclass SIMD_FP8_CVTL<bits<2>sz, string asm, ValueType dty, SDPatternOperator Op> {
7054  let Uses=[FPMR, FPCR], mayLoad = 1 in {
7055    def NAME : BaseSIMDMixedTwoVector<0b0, 0b1, sz, 0b10111, V64, V128,
7056                                      asm, ".8h", ".8b", []>;
7057    def NAME#2 : BaseSIMDMixedTwoVector<0b1, 0b1, sz, 0b10111, V128, V128,
7058                                        asm#2, ".8h", ".16b", []>;
7059  }
7060  def : Pat<(dty (Op (v8i8 V64:$Rn))),
7061            (!cast<Instruction>(NAME) V64:$Rn)>;
7062
7063  def : Pat<(dty (Op (v16i8 V128:$Rn))),
7064            (!cast<Instruction>(NAME#2) V128:$Rn)>;
7065}
7066
7067class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
7068                           bits<5> opcode, RegisterOperand regtype, string asm,
7069                           string kind, string zero, ValueType dty,
7070                           ValueType sty, SDNode OpNode>
7071  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7072      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
7073      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
7074      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
7075    Sched<[!if(Q, WriteVq, WriteVd)]> {
7076  bits<5> Rd;
7077  bits<5> Rn;
7078  let Inst{31}    = 0;
7079  let Inst{30}    = Q;
7080  let Inst{29}    = U;
7081  let Inst{28-24} = 0b01110;
7082  let Inst{23-22} = size;
7083  let Inst{21} = 0b1;
7084  let Inst{20-19} = size2;
7085  let Inst{18-17} = 0b00;
7086  let Inst{16-12} = opcode;
7087  let Inst{11-10} = 0b10;
7088  let Inst{9-5}   = Rn;
7089  let Inst{4-0}   = Rd;
7090}
7091
7092// Comparisons support all element sizes, except 1xD.
7093multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
7094                            SDNode OpNode> {
7095  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
7096                                     asm, ".8b", "0",
7097                                     v8i8, v8i8, OpNode>;
7098  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
7099                                     asm, ".16b", "0",
7100                                     v16i8, v16i8, OpNode>;
7101  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
7102                                     asm, ".4h", "0",
7103                                     v4i16, v4i16, OpNode>;
7104  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
7105                                     asm, ".8h", "0",
7106                                     v8i16, v8i16, OpNode>;
7107  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
7108                                     asm, ".2s", "0",
7109                                     v2i32, v2i32, OpNode>;
7110  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
7111                                     asm, ".4s", "0",
7112                                     v4i32, v4i32, OpNode>;
7113  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
7114                                     asm, ".2d", "0",
7115                                     v2i64, v2i64, OpNode>;
7116}
7117
7118// FP Comparisons support only S and D element sizes (and H for v8.2a).
7119multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
7120                              string asm, SDNode OpNode> {
7121
7122  let mayRaiseFPException = 1, Uses = [FPCR] in {
7123  let Predicates = [HasNEON, HasFullFP16] in {
7124  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
7125                                     asm, ".4h", "0.0",
7126                                     v4i16, v4f16, OpNode>;
7127  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
7128                                     asm, ".8h", "0.0",
7129                                     v8i16, v8f16, OpNode>;
7130  } // Predicates = [HasNEON, HasFullFP16]
7131  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
7132                                     asm, ".2s", "0.0",
7133                                     v2i32, v2f32, OpNode>;
7134  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
7135                                     asm, ".4s", "0.0",
7136                                     v4i32, v4f32, OpNode>;
7137  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
7138                                     asm, ".2d", "0.0",
7139                                     v2i64, v2f64, OpNode>;
7140  }
7141
7142  let Predicates = [HasNEON, HasFullFP16] in {
7143  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
7144                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
7145  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
7146                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
7147  }
7148  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
7149                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
7150  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
7151                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
7152  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
7153                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
7154  let Predicates = [HasNEON, HasFullFP16] in {
7155  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
7156                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
7157  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
7158                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
7159  }
7160  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
7161                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
7162  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
7163                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
7164  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
7165                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
7166}
7167
7168let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
7169class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
7170                             RegisterOperand outtype, RegisterOperand intype,
7171                             string asm, string VdTy, string VnTy,
7172                             list<dag> pattern>
7173  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
7174      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
7175    Sched<[WriteVq]> {
7176  bits<5> Rd;
7177  bits<5> Rn;
7178  let Inst{31}    = 0;
7179  let Inst{30}    = Q;
7180  let Inst{29}    = U;
7181  let Inst{28-24} = 0b01110;
7182  let Inst{23-22} = size;
7183  let Inst{21-17} = 0b10000;
7184  let Inst{16-12} = opcode;
7185  let Inst{11-10} = 0b10;
7186  let Inst{9-5}   = Rn;
7187  let Inst{4-0}   = Rd;
7188}
7189
7190let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
7191class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
7192                             RegisterOperand outtype, RegisterOperand intype,
7193                             string asm, string VdTy, string VnTy,
7194                             list<dag> pattern>
7195  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
7196      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
7197    Sched<[WriteVq]> {
7198  bits<5> Rd;
7199  bits<5> Rn;
7200  let Inst{31}    = 0;
7201  let Inst{30}    = Q;
7202  let Inst{29}    = U;
7203  let Inst{28-24} = 0b01110;
7204  let Inst{23-22} = size;
7205  let Inst{21-17} = 0b10000;
7206  let Inst{16-12} = opcode;
7207  let Inst{11-10} = 0b10;
7208  let Inst{9-5}   = Rn;
7209  let Inst{4-0}   = Rd;
7210}
7211
7212multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
7213  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
7214                                    asm, ".4s", ".4h", []>;
7215  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
7216                                    asm#"2", ".4s", ".8h", []>;
7217  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
7218                                    asm, ".2d", ".2s", []>;
7219  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
7220                                    asm#"2", ".2d", ".4s", []>;
7221}
7222
7223multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
7224  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
7225                                    asm, ".4h", ".4s", []>;
7226  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
7227                                    asm#"2", ".8h", ".4s", []>;
7228  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
7229                                    asm, ".2s", ".2d", []>;
7230  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
7231                                    asm#"2", ".4s", ".2d", []>;
7232}
7233
7234multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
7235                                     SDPatternOperator OpNode> {
7236  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
7237                                     asm, ".2s", ".2d",
7238                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
7239  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
7240                                    asm#"2", ".4s", ".2d", []>;
7241
7242  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
7243            (!cast<Instruction>(NAME # "v4f32")
7244                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
7245}
7246
7247//----------------------------------------------------------------------------
7248// AdvSIMD three register different-size vector instructions.
7249//----------------------------------------------------------------------------
7250
7251let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7252class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
7253                      RegisterOperand outtype, RegisterOperand intype1,
7254                      RegisterOperand intype2, string asm,
7255                      string outkind, string inkind1, string inkind2,
7256                      list<dag> pattern>
7257  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
7258      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
7259      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
7260    Sched<[WriteVq]> {
7261  bits<5> Rd;
7262  bits<5> Rn;
7263  bits<5> Rm;
7264  let Inst{31}    = 0;
7265  let Inst{30}    = size{0};
7266  let Inst{29}    = U;
7267  let Inst{28-24} = 0b01110;
7268  let Inst{23-22} = size{2-1};
7269  let Inst{21}    = 1;
7270  let Inst{20-16} = Rm;
7271  let Inst{15-12} = opcode;
7272  let Inst{11-10} = 0b00;
7273  let Inst{9-5}   = Rn;
7274  let Inst{4-0}   = Rd;
7275}
7276
7277let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7278class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
7279                      RegisterOperand outtype, RegisterOperand intype1,
7280                      RegisterOperand intype2, string asm,
7281                      string outkind, string inkind1, string inkind2,
7282                      list<dag> pattern>
7283  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
7284      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
7285      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
7286    Sched<[WriteVq]> {
7287  bits<5> Rd;
7288  bits<5> Rn;
7289  bits<5> Rm;
7290  let Inst{31}    = 0;
7291  let Inst{30}    = size{0};
7292  let Inst{29}    = U;
7293  let Inst{28-24} = 0b01110;
7294  let Inst{23-22} = size{2-1};
7295  let Inst{21}    = 1;
7296  let Inst{20-16} = Rm;
7297  let Inst{15-12} = opcode;
7298  let Inst{11-10} = 0b00;
7299  let Inst{9-5}   = Rn;
7300  let Inst{4-0}   = Rd;
7301}
7302
7303// FIXME: TableGen doesn't know how to deal with expanded types that also
7304//        change the element count (in this case, placing the results in
7305//        the high elements of the result register rather than the low
7306//        elements). Until that's fixed, we can't code-gen those.
7307multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
7308                                    Intrinsic IntOp> {
7309  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7310                                                  V64, V128, V128,
7311                                                  asm, ".8b", ".8h", ".8h",
7312     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
7313  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7314                                                  V128, V128, V128,
7315                                                  asm#"2", ".16b", ".8h", ".8h",
7316     []>;
7317  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7318                                                  V64, V128, V128,
7319                                                  asm, ".4h", ".4s", ".4s",
7320     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
7321  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7322                                                  V128, V128, V128,
7323                                                  asm#"2", ".8h", ".4s", ".4s",
7324     []>;
7325  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7326                                                  V64, V128, V128,
7327                                                  asm, ".2s", ".2d", ".2d",
7328     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
7329  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7330                                                  V128, V128, V128,
7331                                                  asm#"2", ".4s", ".2d", ".2d",
7332     []>;
7333
7334
7335  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
7336  // a version attached to an instruction.
7337  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
7338                                                   (v8i16 V128:$Rm))),
7339            (!cast<Instruction>(NAME # "v8i16_v16i8")
7340                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7341                V128:$Rn, V128:$Rm)>;
7342  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
7343                                                    (v4i32 V128:$Rm))),
7344            (!cast<Instruction>(NAME # "v4i32_v8i16")
7345                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7346                V128:$Rn, V128:$Rm)>;
7347  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
7348                                                    (v2i64 V128:$Rm))),
7349            (!cast<Instruction>(NAME # "v2i64_v4i32")
7350                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7351                V128:$Rn, V128:$Rm)>;
7352}
7353
7354multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
7355                                      SDPatternOperator OpNode> {
7356  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7357                                            V128, V64, V64,
7358                                            asm, ".8h", ".8b", ".8b",
7359      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7360  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7361                                            V128, V128, V128,
7362                                            asm#"2", ".8h", ".16b", ".16b", []>;
7363  let Predicates = [HasAES] in {
7364    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
7365                                              V128, V64, V64,
7366                                              asm, ".1q", ".1d", ".1d",
7367        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
7368    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
7369                                              V128, V128, V128,
7370                                              asm#"2", ".1q", ".2d", ".2d",
7371        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
7372                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
7373  }
7374
7375  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
7376                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
7377      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
7378}
7379
7380multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
7381                                 SDPatternOperator OpNode> {
7382  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7383                                                  V128, V64, V64,
7384                                                  asm, ".4s", ".4h", ".4h",
7385      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7386  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7387                                                  V128, V128, V128,
7388                                                  asm#"2", ".4s", ".8h", ".8h",
7389      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7390                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7391  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7392                                                  V128, V64, V64,
7393                                                  asm, ".2d", ".2s", ".2s",
7394      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7395  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7396                                                  V128, V128, V128,
7397                                                  asm#"2", ".2d", ".4s", ".4s",
7398      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7399                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7400}
7401
7402multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
7403                                  SDPatternOperator OpNode = null_frag> {
7404  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7405                                                  V128, V64, V64,
7406                                                  asm, ".8h", ".8b", ".8b",
7407      [(set (v8i16 V128:$Rd),
7408            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
7409  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7410                                                 V128, V128, V128,
7411                                                 asm#"2", ".8h", ".16b", ".16b",
7412      [(set (v8i16 V128:$Rd),
7413            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7414                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
7415  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7416                                                  V128, V64, V64,
7417                                                  asm, ".4s", ".4h", ".4h",
7418      [(set (v4i32 V128:$Rd),
7419            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
7420  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7421                                                  V128, V128, V128,
7422                                                  asm#"2", ".4s", ".8h", ".8h",
7423      [(set (v4i32 V128:$Rd),
7424            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7425                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7426  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7427                                                  V128, V64, V64,
7428                                                  asm, ".2d", ".2s", ".2s",
7429      [(set (v2i64 V128:$Rd),
7430            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
7431  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7432                                                  V128, V128, V128,
7433                                                  asm#"2", ".2d", ".4s", ".4s",
7434      [(set (v2i64 V128:$Rd),
7435            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7436                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7437}
7438
7439multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
7440                                          string asm,
7441                                          SDPatternOperator OpNode> {
7442  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7443                                                  V128, V64, V64,
7444                                                  asm, ".8h", ".8b", ".8b",
7445    [(set (v8i16 V128:$dst),
7446          (add (v8i16 V128:$Rd),
7447               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
7448  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7449                                                 V128, V128, V128,
7450                                                 asm#"2", ".8h", ".16b", ".16b",
7451    [(set (v8i16 V128:$dst),
7452          (add (v8i16 V128:$Rd),
7453               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7454                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
7455  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7456                                                  V128, V64, V64,
7457                                                  asm, ".4s", ".4h", ".4h",
7458    [(set (v4i32 V128:$dst),
7459          (add (v4i32 V128:$Rd),
7460               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
7461  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7462                                                  V128, V128, V128,
7463                                                  asm#"2", ".4s", ".8h", ".8h",
7464    [(set (v4i32 V128:$dst),
7465          (add (v4i32 V128:$Rd),
7466               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7467                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
7468  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7469                                                  V128, V64, V64,
7470                                                  asm, ".2d", ".2s", ".2s",
7471    [(set (v2i64 V128:$dst),
7472          (add (v2i64 V128:$Rd),
7473               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
7474  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7475                                                  V128, V128, V128,
7476                                                  asm#"2", ".2d", ".4s", ".4s",
7477    [(set (v2i64 V128:$dst),
7478          (add (v2i64 V128:$Rd),
7479               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7480                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
7481}
7482
7483multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
7484                                  SDPatternOperator OpNode = null_frag> {
7485  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7486                                                  V128, V64, V64,
7487                                                  asm, ".8h", ".8b", ".8b",
7488      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7489  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7490                                                 V128, V128, V128,
7491                                                 asm#"2", ".8h", ".16b", ".16b",
7492      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7493                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7494  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7495                                                  V128, V64, V64,
7496                                                  asm, ".4s", ".4h", ".4h",
7497      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7498  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7499                                                  V128, V128, V128,
7500                                                  asm#"2", ".4s", ".8h", ".8h",
7501      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7502                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7503  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7504                                                  V128, V64, V64,
7505                                                  asm, ".2d", ".2s", ".2s",
7506      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7507  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7508                                                  V128, V128, V128,
7509                                                  asm#"2", ".2d", ".4s", ".4s",
7510      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7511                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7512}
7513
7514multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
7515                                      string asm,
7516                                      SDPatternOperator OpNode> {
7517  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7518                                                  V128, V64, V64,
7519                                                  asm, ".8h", ".8b", ".8b",
7520    [(set (v8i16 V128:$dst),
7521          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7522  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7523                                                 V128, V128, V128,
7524                                                 asm#"2", ".8h", ".16b", ".16b",
7525    [(set (v8i16 V128:$dst),
7526          (OpNode (v8i16 V128:$Rd),
7527                  (extract_high_v16i8 (v16i8 V128:$Rn)),
7528                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7529  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7530                                                  V128, V64, V64,
7531                                                  asm, ".4s", ".4h", ".4h",
7532    [(set (v4i32 V128:$dst),
7533          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7534  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7535                                                  V128, V128, V128,
7536                                                  asm#"2", ".4s", ".8h", ".8h",
7537    [(set (v4i32 V128:$dst),
7538          (OpNode (v4i32 V128:$Rd),
7539                  (extract_high_v8i16 (v8i16 V128:$Rn)),
7540                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7541  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7542                                                  V128, V64, V64,
7543                                                  asm, ".2d", ".2s", ".2s",
7544    [(set (v2i64 V128:$dst),
7545          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7546  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7547                                                  V128, V128, V128,
7548                                                  asm#"2", ".2d", ".4s", ".4s",
7549    [(set (v2i64 V128:$dst),
7550          (OpNode (v2i64 V128:$Rd),
7551                  (extract_high_v4i32 (v4i32 V128:$Rn)),
7552                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7553}
7554
7555multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
7556                                           SDPatternOperator Accum> {
7557  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7558                                                  V128, V64, V64,
7559                                                  asm, ".4s", ".4h", ".4h",
7560    [(set (v4i32 V128:$dst),
7561          (Accum (v4i32 V128:$Rd),
7562                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7563                                                (v4i16 V64:$Rm)))))]>;
7564  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7565                                                  V128, V128, V128,
7566                                                  asm#"2", ".4s", ".8h", ".8h",
7567    [(set (v4i32 V128:$dst),
7568          (Accum (v4i32 V128:$Rd),
7569                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
7570                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7571  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7572                                                  V128, V64, V64,
7573                                                  asm, ".2d", ".2s", ".2s",
7574    [(set (v2i64 V128:$dst),
7575          (Accum (v2i64 V128:$Rd),
7576                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
7577                                                (v2i32 V64:$Rm)))))]>;
7578  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7579                                                  V128, V128, V128,
7580                                                  asm#"2", ".2d", ".4s", ".4s",
7581    [(set (v2i64 V128:$dst),
7582          (Accum (v2i64 V128:$Rd),
7583                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
7584                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7585}
7586
7587multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
7588                                  SDPatternOperator OpNode> {
7589  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7590                                                  V128, V128, V64,
7591                                                  asm, ".8h", ".8h", ".8b",
7592       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
7593  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7594                                                  V128, V128, V128,
7595                                                  asm#"2", ".8h", ".8h", ".16b",
7596       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7597                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7598  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7599                                                  V128, V128, V64,
7600                                                  asm, ".4s", ".4s", ".4h",
7601       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
7602  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7603                                                  V128, V128, V128,
7604                                                  asm#"2", ".4s", ".4s", ".8h",
7605       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7606                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7607  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7608                                                  V128, V128, V64,
7609                                                  asm, ".2d", ".2d", ".2s",
7610       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
7611  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7612                                                  V128, V128, V128,
7613                                                  asm#"2", ".2d", ".2d", ".4s",
7614       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7615                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7616}
7617
7618//----------------------------------------------------------------------------
7619// AdvSIMD bitwise extract from vector
7620//----------------------------------------------------------------------------
7621
7622class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
7623                             string asm, string kind>
7624  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
7625      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
7626      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
7627      [(set (vty regtype:$Rd),
7628            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
7629    Sched<[!if(size, WriteVq, WriteVd)]> {
7630  bits<5> Rd;
7631  bits<5> Rn;
7632  bits<5> Rm;
7633  bits<4> imm;
7634  let Inst{31}    = 0;
7635  let Inst{30}    = size;
7636  let Inst{29-21} = 0b101110000;
7637  let Inst{20-16} = Rm;
7638  let Inst{15}    = 0;
7639  let Inst{14-11} = imm;
7640  let Inst{10}    = 0;
7641  let Inst{9-5}   = Rn;
7642  let Inst{4-0}   = Rd;
7643}
7644
7645
7646multiclass SIMDBitwiseExtract<string asm> {
7647  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
7648    let imm{3} = 0;
7649  }
7650  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
7651}
7652
7653//----------------------------------------------------------------------------
7654// AdvSIMD zip vector
7655//----------------------------------------------------------------------------
7656
7657class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
7658                        string asm, string kind, SDNode OpNode, ValueType valty>
7659  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7660      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
7661      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
7662      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
7663    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
7664  bits<5> Rd;
7665  bits<5> Rn;
7666  bits<5> Rm;
7667  let Inst{31}    = 0;
7668  let Inst{30}    = size{0};
7669  let Inst{29-24} = 0b001110;
7670  let Inst{23-22} = size{2-1};
7671  let Inst{21}    = 0;
7672  let Inst{20-16} = Rm;
7673  let Inst{15}    = 0;
7674  let Inst{14-12} = opc;
7675  let Inst{11-10} = 0b10;
7676  let Inst{9-5}   = Rn;
7677  let Inst{4-0}   = Rd;
7678}
7679
7680multiclass SIMDZipVector<bits<3>opc, string asm,
7681                         SDNode OpNode> {
7682  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
7683      asm, ".8b", OpNode, v8i8>;
7684  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
7685      asm, ".16b", OpNode, v16i8>;
7686  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
7687      asm, ".4h", OpNode, v4i16>;
7688  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
7689      asm, ".8h", OpNode, v8i16>;
7690  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
7691      asm, ".2s", OpNode, v2i32>;
7692  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
7693      asm, ".4s", OpNode, v4i32>;
7694  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
7695      asm, ".2d", OpNode, v2i64>;
7696
7697  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
7698        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7699  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
7700        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7701  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7702        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7703  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7704        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7705  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7706        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7707  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7708        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7709  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7710        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7711}
7712
7713//----------------------------------------------------------------------------
7714// AdvSIMD three register scalar instructions
7715//----------------------------------------------------------------------------
7716
7717let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7718class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7719                        RegisterClass regtype, string asm,
7720                        list<dag> pattern>
7721  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7722      "\t$Rd, $Rn, $Rm", "", pattern>,
7723    Sched<[WriteVd]> {
7724  bits<5> Rd;
7725  bits<5> Rn;
7726  bits<5> Rm;
7727  let Inst{31-30} = 0b01;
7728  let Inst{29}    = U;
7729  let Inst{28-24} = 0b11110;
7730  let Inst{23-21} = size;
7731  let Inst{20-16} = Rm;
7732  let Inst{15-11} = opcode;
7733  let Inst{10}    = 1;
7734  let Inst{9-5}   = Rn;
7735  let Inst{4-0}   = Rd;
7736}
7737
7738let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7739class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7740                        dag oops, dag iops, string asm,
7741            list<dag> pattern>
7742  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7743    Sched<[WriteVd]> {
7744  bits<5> Rd;
7745  bits<5> Rn;
7746  bits<5> Rm;
7747  let Inst{31-30} = 0b01;
7748  let Inst{29}    = U;
7749  let Inst{28-24} = 0b11110;
7750  let Inst{23-22} = size;
7751  let Inst{21}    = R;
7752  let Inst{20-16} = Rm;
7753  let Inst{15-11} = opcode;
7754  let Inst{10}    = 1;
7755  let Inst{9-5}   = Rn;
7756  let Inst{4-0}   = Rd;
7757}
7758
7759multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7760                            SDPatternOperator OpNode> {
7761  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7762    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7763}
7764
7765multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7766                               SDPatternOperator OpNode> {
7767  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7768    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7769  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7770  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7771  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7772
7773  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7774            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7775  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7776            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7777}
7778
7779multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7780                             SDPatternOperator OpNode> {
7781  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7782                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7783  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7784}
7785
7786multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7787  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7788                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7789                                     asm, []>;
7790  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7791                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7792                                     asm, []>;
7793}
7794
7795multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7796                             SDPatternOperator OpNode = null_frag,
7797                             Predicate pred = HasNEON> {
7798  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7799    let Predicates = [pred] in {
7800    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7801      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7802    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7803      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7804    }
7805    let Predicates = [pred, HasFullFP16] in {
7806    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7807      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7808    }
7809  }
7810
7811  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7812            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7813}
7814
7815multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7816                                SDPatternOperator OpNode = null_frag> {
7817  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7818    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7819      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7820    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7821      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7822    let Predicates = [HasNEON, HasFullFP16] in {
7823    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7824      []>;
7825    } // Predicates = [HasNEON, HasFullFP16]
7826  }
7827
7828  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7829            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7830}
7831
7832class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7833              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7834  : I<oops, iops, asm,
7835      "\t$Rd, $Rn, $Rm", cstr, pat>,
7836    Sched<[WriteVd]> {
7837  bits<5> Rd;
7838  bits<5> Rn;
7839  bits<5> Rm;
7840  let Inst{31-30} = 0b01;
7841  let Inst{29}    = U;
7842  let Inst{28-24} = 0b11110;
7843  let Inst{23-22} = size;
7844  let Inst{21}    = 1;
7845  let Inst{20-16} = Rm;
7846  let Inst{15-11} = opcode;
7847  let Inst{10}    = 0;
7848  let Inst{9-5}   = Rn;
7849  let Inst{4-0}   = Rd;
7850}
7851
7852let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7853multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7854                                  SDPatternOperator OpNode = null_frag> {
7855  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7856                                      (outs FPR32:$Rd),
7857                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7858  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7859                                      (outs FPR64:$Rd),
7860                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7861            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7862}
7863
7864let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7865multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7866                                  SDPatternOperator OpNode = null_frag> {
7867  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7868                                      (outs FPR32:$dst),
7869                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7870                                      asm, "$Rd = $dst", []>;
7871  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7872                                      (outs FPR64:$dst),
7873                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7874                                      asm, "$Rd = $dst",
7875            [(set (i64 FPR64:$dst),
7876                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7877}
7878
7879//----------------------------------------------------------------------------
7880// AdvSIMD two register scalar instructions
7881//----------------------------------------------------------------------------
7882
7883let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7884class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7885                        RegisterClass regtype, RegisterClass regtype2,
7886                        string asm, list<dag> pat>
7887  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7888      "\t$Rd, $Rn", "", pat>,
7889    Sched<[WriteVd]> {
7890  bits<5> Rd;
7891  bits<5> Rn;
7892  let Inst{31-30} = 0b01;
7893  let Inst{29}    = U;
7894  let Inst{28-24} = 0b11110;
7895  let Inst{23-22} = size;
7896  let Inst{21} = 0b1;
7897  let Inst{20-19} = size2;
7898  let Inst{18-17} = 0b00;
7899  let Inst{16-12} = opcode;
7900  let Inst{11-10} = 0b10;
7901  let Inst{9-5}   = Rn;
7902  let Inst{4-0}   = Rd;
7903}
7904
7905let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7906class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7907                        RegisterClass regtype, RegisterClass regtype2,
7908                        string asm, list<dag> pat>
7909  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7910      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7911    Sched<[WriteVd]> {
7912  bits<5> Rd;
7913  bits<5> Rn;
7914  let Inst{31-30} = 0b01;
7915  let Inst{29}    = U;
7916  let Inst{28-24} = 0b11110;
7917  let Inst{23-22} = size;
7918  let Inst{21-17} = 0b10000;
7919  let Inst{16-12} = opcode;
7920  let Inst{11-10} = 0b10;
7921  let Inst{9-5}   = Rn;
7922  let Inst{4-0}   = Rd;
7923}
7924
7925
7926let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7927class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7928                        RegisterClass regtype, string asm, string zero>
7929  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7930      "\t$Rd, $Rn, #" # zero, "", []>,
7931    Sched<[WriteVd]> {
7932  bits<5> Rd;
7933  bits<5> Rn;
7934  let Inst{31-30} = 0b01;
7935  let Inst{29}    = U;
7936  let Inst{28-24} = 0b11110;
7937  let Inst{23-22} = size;
7938  let Inst{21} = 0b1;
7939  let Inst{20-19} = size2;
7940  let Inst{18-17} = 0b00;
7941  let Inst{16-12} = opcode;
7942  let Inst{11-10} = 0b10;
7943  let Inst{9-5}   = Rn;
7944  let Inst{4-0}   = Rd;
7945}
7946
7947let mayRaiseFPException = 1, Uses = [FPCR] in
7948class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7949  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7950     [(set (f32 FPR32:$Rd), (AArch64fcvtxnsdr (f64 FPR64:$Rn)))]>,
7951    Sched<[WriteVd]> {
7952  bits<5> Rd;
7953  bits<5> Rn;
7954  let Inst{31-17} = 0b011111100110000;
7955  let Inst{16-12} = opcode;
7956  let Inst{11-10} = 0b10;
7957  let Inst{9-5}   = Rn;
7958  let Inst{4-0}   = Rd;
7959}
7960
7961multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7962                             SDPatternOperator OpNode> {
7963  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7964
7965  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7966            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7967}
7968
7969multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7970                              SDPatternOperator OpNode> {
7971  let mayRaiseFPException = 1, Uses = [FPCR] in {
7972  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7973  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7974  let Predicates = [HasNEON, HasFullFP16] in {
7975  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7976  }
7977  }
7978
7979  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7980                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7981  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7982                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7983  let Predicates = [HasNEON, HasFullFP16] in {
7984  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7985                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7986  }
7987
7988  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7989            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7990}
7991
7992multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7993                          SDPatternOperator OpNode = null_frag,
7994                          list<Predicate> preds = []> {
7995  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7996    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7997
7998  let Predicates = preds in {
7999  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
8000            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
8001  }
8002}
8003
8004let mayRaiseFPException = 1, Uses = [FPCR] in
8005multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
8006  let Predicates = [HasNEONandIsStreamingSafe] in {
8007  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
8008  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
8009  }
8010  let Predicates = [HasNEONandIsStreamingSafe, HasFullFP16] in {
8011  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
8012  }
8013}
8014
8015let mayRaiseFPException = 1, Uses = [FPCR] in
8016multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
8017                              SDPatternOperator OpNode> {
8018  let Predicates = [HasNEONandIsStreamingSafe] in {
8019  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
8020                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
8021  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
8022                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
8023  }
8024  let Predicates = [HasNEONandIsStreamingSafe, HasFullFP16] in {
8025  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
8026                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
8027  }
8028}
8029
8030multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
8031                             SDPatternOperator OpNode = null_frag> {
8032  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8033    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
8034           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
8035    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
8036           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8037    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
8038    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
8039  }
8040
8041  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
8042            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
8043}
8044
8045multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
8046                                 Intrinsic OpNode> {
8047  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8048    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
8049        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
8050    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
8051        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
8052    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
8053    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
8054  }
8055
8056  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
8057            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
8058}
8059
8060
8061
8062let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8063multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
8064                                 SDPatternOperator OpNode = null_frag> {
8065  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
8066        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
8067  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
8068  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
8069}
8070
8071//----------------------------------------------------------------------------
8072// AdvSIMD scalar pairwise instructions
8073//----------------------------------------------------------------------------
8074
8075let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8076class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
8077                        RegisterOperand regtype, RegisterOperand vectype,
8078                        string asm, string kind>
8079  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
8080      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
8081    Sched<[WriteVd]> {
8082  bits<5> Rd;
8083  bits<5> Rn;
8084  let Inst{31-30} = 0b01;
8085  let Inst{29}    = U;
8086  let Inst{28-24} = 0b11110;
8087  let Inst{23-22} = size;
8088  let Inst{21-17} = 0b11000;
8089  let Inst{16-12} = opcode;
8090  let Inst{11-10} = 0b10;
8091  let Inst{9-5}   = Rn;
8092  let Inst{4-0}   = Rd;
8093}
8094
8095multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
8096  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
8097                                      asm, ".2d">;
8098}
8099
8100let mayRaiseFPException = 1, Uses = [FPCR] in
8101multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
8102  let Predicates = [HasNEON, HasFullFP16] in {
8103  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
8104                                      asm, ".2h">;
8105  }
8106  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
8107                                      asm, ".2s">;
8108  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
8109                                      asm, ".2d">;
8110}
8111
8112//----------------------------------------------------------------------------
8113// AdvSIMD across lanes instructions
8114//----------------------------------------------------------------------------
8115
8116let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8117class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
8118                          RegisterClass regtype, RegisterOperand vectype,
8119                          string asm, string kind, list<dag> pattern>
8120  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
8121      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
8122    Sched<[!if(Q, WriteVq, WriteVd)]> {
8123  bits<5> Rd;
8124  bits<5> Rn;
8125  let Inst{31}    = 0;
8126  let Inst{30}    = Q;
8127  let Inst{29}    = U;
8128  let Inst{28-24} = 0b01110;
8129  let Inst{23-22} = size;
8130  let Inst{21-17} = 0b11000;
8131  let Inst{16-12} = opcode;
8132  let Inst{11-10} = 0b10;
8133  let Inst{9-5}   = Rn;
8134  let Inst{4-0}   = Rd;
8135}
8136
8137multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
8138                              string asm> {
8139  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
8140                                   asm, ".8b", []>;
8141  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
8142                                   asm, ".16b", []>;
8143  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
8144                                   asm, ".4h", []>;
8145  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
8146                                   asm, ".8h", []>;
8147  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
8148                                   asm, ".4s", []>;
8149}
8150
8151multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
8152  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
8153                                   asm, ".8b", []>;
8154  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
8155                                   asm, ".16b", []>;
8156  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
8157                                   asm, ".4h", []>;
8158  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
8159                                   asm, ".8h", []>;
8160  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
8161                                   asm, ".4s", []>;
8162}
8163
8164let mayRaiseFPException = 1, Uses = [FPCR] in
8165multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
8166                            SDPatternOperator intOp> {
8167  let Predicates = [HasNEON, HasFullFP16] in {
8168  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
8169                                   asm, ".4h",
8170        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
8171  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
8172                                   asm, ".8h",
8173        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
8174  } // Predicates = [HasNEON, HasFullFP16]
8175  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
8176                                   asm, ".4s",
8177        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
8178}
8179
8180//----------------------------------------------------------------------------
8181// AdvSIMD INS/DUP instructions
8182//----------------------------------------------------------------------------
8183
8184// FIXME: There has got to be a better way to factor these. ugh.
8185
8186class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
8187                     string operands, string constraints, list<dag> pattern>
8188  : I<outs, ins, asm, operands, constraints, pattern>,
8189    Sched<[!if(Q, WriteVq, WriteVd)]> {
8190  bits<5> Rd;
8191  bits<5> Rn;
8192  let Inst{31} = 0;
8193  let Inst{30} = Q;
8194  let Inst{29} = op;
8195  let Inst{28-21} = 0b01110000;
8196  let Inst{15} = 0;
8197  let Inst{10} = 1;
8198  let Inst{9-5} = Rn;
8199  let Inst{4-0} = Rd;
8200}
8201
8202class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
8203                      RegisterOperand vecreg, RegisterClass regtype>
8204  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
8205                   "{\t$Rd" # size # ", $Rn" #
8206                   "|" # size # "\t$Rd, $Rn}", "",
8207                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
8208  let Inst{20-16} = imm5;
8209  let Inst{14-11} = 0b0001;
8210}
8211
8212class SIMDDupFromElement<bit Q, string dstkind, string srckind,
8213                         ValueType vectype, ValueType insreg,
8214                         RegisterOperand vecreg, Operand idxtype,
8215                         SDNode OpNode>
8216  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
8217                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
8218                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
8219                 [(set (vectype vecreg:$Rd),
8220                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
8221  let Inst{14-11} = 0b0000;
8222}
8223
8224class SIMDDup64FromElement
8225  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
8226                       VectorIndexD, AArch64duplane64> {
8227  bits<1> idx;
8228  let Inst{20} = idx;
8229  let Inst{19-16} = 0b1000;
8230}
8231
8232class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
8233                           RegisterOperand vecreg>
8234  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
8235                       VectorIndexS, AArch64duplane32> {
8236  bits<2> idx;
8237  let Inst{20-19} = idx;
8238  let Inst{18-16} = 0b100;
8239}
8240
8241class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
8242                           RegisterOperand vecreg>
8243  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
8244                       VectorIndexH, AArch64duplane16> {
8245  bits<3> idx;
8246  let Inst{20-18} = idx;
8247  let Inst{17-16} = 0b10;
8248}
8249
8250class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
8251                          RegisterOperand vecreg>
8252  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
8253                       VectorIndexB, AArch64duplane8> {
8254  bits<4> idx;
8255  let Inst{20-17} = idx;
8256  let Inst{16} = 1;
8257}
8258
8259class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
8260                  Operand idxtype, string asm, list<dag> pattern>
8261  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
8262                   "{\t$Rd, $Rn" # size # "$idx" #
8263                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
8264  let Inst{14-11} = imm4;
8265}
8266
8267class SIMDSMov<bit Q, string size, RegisterClass regtype,
8268               Operand idxtype>
8269  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
8270class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
8271               Operand idxtype>
8272  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
8273      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
8274
8275class SIMDMovAlias<string asm, string size, Instruction inst,
8276                   RegisterClass regtype, Operand idxtype>
8277    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
8278                    "|" # size # "\t$dst, $src$idx}",
8279                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
8280
8281multiclass SMov {
8282  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
8283  // streaming mode.
8284  let Predicates = [HasNEONandIsStreamingSafe] in {
8285    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
8286      let Inst{20-16} = 0b00001;
8287    }
8288    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
8289      let Inst{20-16} = 0b00001;
8290    }
8291    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
8292      let Inst{20-16} = 0b00010;
8293    }
8294    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
8295      let Inst{20-16} = 0b00010;
8296    }
8297    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
8298      let Inst{20-16} = 0b00100;
8299    }
8300  }
8301  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
8302    bits<4> idx;
8303    let Inst{20-17} = idx;
8304    let Inst{16} = 1;
8305  }
8306  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
8307    bits<4> idx;
8308    let Inst{20-17} = idx;
8309    let Inst{16} = 1;
8310  }
8311  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
8312    bits<3> idx;
8313    let Inst{20-18} = idx;
8314    let Inst{17-16} = 0b10;
8315  }
8316  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
8317    bits<3> idx;
8318    let Inst{20-18} = idx;
8319    let Inst{17-16} = 0b10;
8320  }
8321  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
8322    bits<2> idx;
8323    let Inst{20-19} = idx;
8324    let Inst{18-16} = 0b100;
8325  }
8326}
8327
8328multiclass UMov {
8329  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
8330  // streaming mode.
8331  let Predicates = [HasNEONandIsStreamingSafe] in {
8332    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
8333      let Inst{20-16} = 0b00001;
8334    }
8335    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
8336      let Inst{20-16} = 0b00010;
8337    }
8338    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
8339      let Inst{20-16} = 0b00100;
8340    }
8341    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
8342      let Inst{20-16} = 0b01000;
8343    }
8344    def : SIMDMovAlias<"mov", ".s",
8345                       !cast<Instruction>(NAME # vi32_idx0),
8346                       GPR32, VectorIndex0>;
8347    def : SIMDMovAlias<"mov", ".d",
8348                       !cast<Instruction>(NAME # vi64_idx0),
8349                       GPR64, VectorIndex0>;
8350  }
8351  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
8352    bits<4> idx;
8353    let Inst{20-17} = idx;
8354    let Inst{16} = 1;
8355  }
8356  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
8357    bits<3> idx;
8358    let Inst{20-18} = idx;
8359    let Inst{17-16} = 0b10;
8360  }
8361  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
8362    bits<2> idx;
8363    let Inst{20-19} = idx;
8364    let Inst{18-16} = 0b100;
8365  }
8366  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
8367    bits<1> idx;
8368    let Inst{20} = idx;
8369    let Inst{19-16} = 0b1000;
8370  }
8371  def : SIMDMovAlias<"mov", ".s",
8372                     !cast<Instruction>(NAME#"vi32"),
8373                     GPR32, VectorIndexS>;
8374  def : SIMDMovAlias<"mov", ".d",
8375                     !cast<Instruction>(NAME#"vi64"),
8376                     GPR64, VectorIndexD>;
8377}
8378
8379class SIMDInsFromMain<string size, ValueType vectype,
8380                      RegisterClass regtype, Operand idxtype>
8381  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
8382                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
8383                   "{\t$Rd" # size # "$idx, $Rn" #
8384                   "|" # size # "\t$Rd$idx, $Rn}",
8385                   "$Rd = $dst",
8386            [(set V128:$dst,
8387              (vector_insert (vectype V128:$Rd), regtype:$Rn, (i64 idxtype:$idx)))]> {
8388  let Inst{14-11} = 0b0011;
8389}
8390
8391class SIMDInsFromElement<string size, ValueType vectype,
8392                         ValueType elttype, Operand idxtype>
8393  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
8394                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
8395                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
8396                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
8397                   "$Rd = $dst",
8398         [(set V128:$dst,
8399               (vector_insert
8400                 (vectype V128:$Rd),
8401                 (elttype (vector_extract (vectype V128:$Rn), (i64 idxtype:$idx2))),
8402                 (i64 idxtype:$idx)))]>;
8403
8404class SIMDInsMainMovAlias<string size, Instruction inst,
8405                          RegisterClass regtype, Operand idxtype>
8406    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
8407                        "|" # size #"\t$dst$idx, $src}",
8408                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
8409class SIMDInsElementMovAlias<string size, Instruction inst,
8410                             Operand idxtype>
8411    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
8412                      # "|" # size #"\t$dst$idx, $src$idx2}",
8413                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
8414
8415
8416multiclass SIMDIns {
8417  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
8418    bits<4> idx;
8419    let Inst{20-17} = idx;
8420    let Inst{16} = 1;
8421  }
8422  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
8423    bits<3> idx;
8424    let Inst{20-18} = idx;
8425    let Inst{17-16} = 0b10;
8426  }
8427  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
8428    bits<2> idx;
8429    let Inst{20-19} = idx;
8430    let Inst{18-16} = 0b100;
8431  }
8432  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
8433    bits<1> idx;
8434    let Inst{20} = idx;
8435    let Inst{19-16} = 0b1000;
8436  }
8437
8438  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
8439    bits<4> idx;
8440    bits<4> idx2;
8441    let Inst{20-17} = idx;
8442    let Inst{16} = 1;
8443    let Inst{14-11} = idx2;
8444  }
8445  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
8446    bits<3> idx;
8447    bits<3> idx2;
8448    let Inst{20-18} = idx;
8449    let Inst{17-16} = 0b10;
8450    let Inst{14-12} = idx2;
8451    let Inst{11} = {?};
8452  }
8453  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
8454    bits<2> idx;
8455    bits<2> idx2;
8456    let Inst{20-19} = idx;
8457    let Inst{18-16} = 0b100;
8458    let Inst{14-13} = idx2;
8459    let Inst{12-11} = {?,?};
8460  }
8461  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
8462    bits<1> idx;
8463    bits<1> idx2;
8464    let Inst{20} = idx;
8465    let Inst{19-16} = 0b1000;
8466    let Inst{14} = idx2;
8467    let Inst{13-11} = {?,?,?};
8468  }
8469
8470  // For all forms of the INS instruction, the "mov" mnemonic is the
8471  // preferred alias. Why they didn't just call the instruction "mov" in
8472  // the first place is a very good question indeed...
8473  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
8474                         GPR32, VectorIndexB>;
8475  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
8476                         GPR32, VectorIndexH>;
8477  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
8478                         GPR32, VectorIndexS>;
8479  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
8480                         GPR64, VectorIndexD>;
8481
8482  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
8483                         VectorIndexB>;
8484  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
8485                         VectorIndexH>;
8486  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
8487                         VectorIndexS>;
8488  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
8489                         VectorIndexD>;
8490}
8491
8492//----------------------------------------------------------------------------
8493// AdvSIMD TBL/TBX
8494//----------------------------------------------------------------------------
8495
8496let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8497class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8498                          RegisterOperand listtype, string asm, string kind>
8499  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
8500       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
8501    Sched<[!if(Q, WriteVq, WriteVd)]> {
8502  bits<5> Vd;
8503  bits<5> Vn;
8504  bits<5> Vm;
8505  let Inst{31}    = 0;
8506  let Inst{30}    = Q;
8507  let Inst{29-21} = 0b001110000;
8508  let Inst{20-16} = Vm;
8509  let Inst{15}    = 0;
8510  let Inst{14-13} = len;
8511  let Inst{12}    = op;
8512  let Inst{11-10} = 0b00;
8513  let Inst{9-5}   = Vn;
8514  let Inst{4-0}   = Vd;
8515}
8516
8517let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8518class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8519                          RegisterOperand listtype, string asm, string kind>
8520  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
8521       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
8522    Sched<[!if(Q, WriteVq, WriteVd)]> {
8523  bits<5> Vd;
8524  bits<5> Vn;
8525  bits<5> Vm;
8526  let Inst{31}    = 0;
8527  let Inst{30}    = Q;
8528  let Inst{29-21} = 0b001110000;
8529  let Inst{20-16} = Vm;
8530  let Inst{15}    = 0;
8531  let Inst{14-13} = len;
8532  let Inst{12}    = op;
8533  let Inst{11-10} = 0b00;
8534  let Inst{9-5}   = Vn;
8535  let Inst{4-0}   = Vd;
8536}
8537
8538class SIMDTableLookupAlias<string asm, Instruction inst,
8539                          RegisterOperand vectype, RegisterOperand listtype>
8540    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
8541                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
8542
8543multiclass SIMDTableLookup<bit op, string asm> {
8544  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
8545                                      asm, ".8b">;
8546  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
8547                                      asm, ".8b">;
8548  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
8549                                      asm, ".8b">;
8550  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
8551                                      asm, ".8b">;
8552  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
8553                                      asm, ".16b">;
8554  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
8555                                      asm, ".16b">;
8556  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
8557                                      asm, ".16b">;
8558  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
8559                                      asm, ".16b">;
8560
8561  def : SIMDTableLookupAlias<asm # ".8b",
8562                         !cast<Instruction>(NAME#"v8i8One"),
8563                         V64, VecListOneConsecutive128>;
8564  def : SIMDTableLookupAlias<asm # ".8b",
8565                         !cast<Instruction>(NAME#"v8i8Two"),
8566                         V64, VecListTwoConsecutive128>;
8567  def : SIMDTableLookupAlias<asm # ".8b",
8568                         !cast<Instruction>(NAME#"v8i8Three"),
8569                         V64, VecListThreeConsecutive128>;
8570  def : SIMDTableLookupAlias<asm # ".8b",
8571                         !cast<Instruction>(NAME#"v8i8Four"),
8572                         V64, VecListFourConsecutive128>;
8573  def : SIMDTableLookupAlias<asm # ".16b",
8574                         !cast<Instruction>(NAME#"v16i8One"),
8575                         V128, VecListOneConsecutive128>;
8576  def : SIMDTableLookupAlias<asm # ".16b",
8577                         !cast<Instruction>(NAME#"v16i8Two"),
8578                         V128, VecListTwoConsecutive128>;
8579  def : SIMDTableLookupAlias<asm # ".16b",
8580                         !cast<Instruction>(NAME#"v16i8Three"),
8581                         V128, VecListThreeConsecutive128>;
8582  def : SIMDTableLookupAlias<asm # ".16b",
8583                         !cast<Instruction>(NAME#"v16i8Four"),
8584                         V128, VecListFourConsecutive128>;
8585}
8586
8587multiclass SIMDTableLookupTied<bit op, string asm> {
8588  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
8589                                      asm, ".8b">;
8590  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
8591                                      asm, ".8b">;
8592  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
8593                                      asm, ".8b">;
8594  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
8595                                      asm, ".8b">;
8596  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
8597                                      asm, ".16b">;
8598  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
8599                                      asm, ".16b">;
8600  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
8601                                      asm, ".16b">;
8602  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
8603                                      asm, ".16b">;
8604
8605  def : SIMDTableLookupAlias<asm # ".8b",
8606                         !cast<Instruction>(NAME#"v8i8One"),
8607                         V64, VecListOneConsecutive128>;
8608  def : SIMDTableLookupAlias<asm # ".8b",
8609                         !cast<Instruction>(NAME#"v8i8Two"),
8610                         V64, VecListTwoConsecutive128>;
8611  def : SIMDTableLookupAlias<asm # ".8b",
8612                         !cast<Instruction>(NAME#"v8i8Three"),
8613                         V64, VecListThreeConsecutive128>;
8614  def : SIMDTableLookupAlias<asm # ".8b",
8615                         !cast<Instruction>(NAME#"v8i8Four"),
8616                         V64, VecListFourConsecutive128>;
8617  def : SIMDTableLookupAlias<asm # ".16b",
8618                         !cast<Instruction>(NAME#"v16i8One"),
8619                         V128, VecListOneConsecutive128>;
8620  def : SIMDTableLookupAlias<asm # ".16b",
8621                         !cast<Instruction>(NAME#"v16i8Two"),
8622                         V128, VecListTwoConsecutive128>;
8623  def : SIMDTableLookupAlias<asm # ".16b",
8624                         !cast<Instruction>(NAME#"v16i8Three"),
8625                         V128, VecListThreeConsecutive128>;
8626  def : SIMDTableLookupAlias<asm # ".16b",
8627                         !cast<Instruction>(NAME#"v16i8Four"),
8628                         V128, VecListFourConsecutive128>;
8629}
8630
8631//----------------------------------------------------------------------------
8632// AdvSIMD LUT
8633//----------------------------------------------------------------------------
8634let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8635class BaseSIMDTableLookupIndexed<bit Q, bits<5> opc,
8636                            RegisterOperand listtype, Operand idx_type,
8637                            string asm, string kind>
8638  : I<(outs V128:$Rd),
8639      (ins listtype:$Rn, V128:$Rm, idx_type:$idx),
8640      asm, "\t$Rd" # kind # ", $Rn, $Rm$idx", "", []>,
8641    Sched<[]> {
8642  bits<5> Rd;
8643  bits<5> Rn;
8644  bits<5> Rm;
8645  let Inst{31}    = 0;
8646  let Inst{30}    = Q;
8647  let Inst{29-24} = 0b001110;
8648  let Inst{23-22} = opc{4-3};
8649  let Inst{21}    = 0;
8650  let Inst{20-16} = Rm;
8651  let Inst{15}    = 0;
8652  let Inst{14-12} = opc{2-0};
8653  let Inst{11-10} = 0b00;
8654  let Inst{9-5}   = Rn;
8655  let Inst{4-0}   = Rd;
8656}
8657
8658multiclass BaseSIMDTableLookupIndexed2<string asm> {
8659  def _B : BaseSIMDTableLookupIndexed<0b1, {0b10,?,?,0b1}, VecListOne16b, VectorIndexS32b_timm, asm, ".16b"> {
8660    bits<2> idx;
8661    let Inst{14-13} = idx;
8662  }
8663  def _H : BaseSIMDTableLookupIndexed<0b1, {0b11,?,?,?}, VecListOne8h, VectorIndexH32b_timm, asm, ".8h" > {
8664    bits<3> idx;
8665    let Inst{14-12} = idx;
8666  }
8667}
8668
8669multiclass BaseSIMDTableLookupIndexed4<string asm> {
8670  def _B : BaseSIMDTableLookupIndexed<0b1, {0b01,?,0b10}, VecListOne16b, VectorIndexD32b_timm, asm, ".16b"> {
8671    bit idx;
8672    let Inst{14} = idx;
8673  }
8674  def _H : BaseSIMDTableLookupIndexed<0b1, {0b01,?,?,0b1}, VecListTwo8h, VectorIndexS32b_timm, asm, ".8h" > {
8675    bits<2> idx;
8676    let Inst{14-13} = idx;
8677  }
8678}
8679
8680//----------------------------------------------------------------------------
8681// AdvSIMD scalar DUP
8682//----------------------------------------------------------------------------
8683let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8684class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
8685                        string asm, string kind, Operand idxtype>
8686  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
8687       "{\t$dst, $src" # kind # "$idx" #
8688       "|\t$dst, $src$idx}", "", []>,
8689    Sched<[WriteVd]> {
8690  bits<5> dst;
8691  bits<5> src;
8692  let Inst{31-21} = 0b01011110000;
8693  let Inst{15-10} = 0b000001;
8694  let Inst{9-5}   = src;
8695  let Inst{4-0}   = dst;
8696}
8697
8698class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
8699      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
8700    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
8701                    # "|\t$dst, $src$index}",
8702                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
8703
8704
8705multiclass SIMDScalarDUP<string asm> {
8706  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
8707    bits<4> idx;
8708    let Inst{20-17} = idx;
8709    let Inst{16} = 1;
8710  }
8711  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
8712    bits<3> idx;
8713    let Inst{20-18} = idx;
8714    let Inst{17-16} = 0b10;
8715  }
8716  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
8717    bits<2> idx;
8718    let Inst{20-19} = idx;
8719    let Inst{18-16} = 0b100;
8720  }
8721  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
8722    bits<1> idx;
8723    let Inst{20} = idx;
8724    let Inst{19-16} = 0b1000;
8725  }
8726
8727  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
8728                                                          VectorIndexD:$idx)))),
8729            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
8730
8731  // 'DUP' mnemonic aliases.
8732  def : SIMDScalarDUPAlias<"dup", ".b",
8733                           !cast<Instruction>(NAME#"i8"),
8734                           FPR8, V128, VectorIndexB>;
8735  def : SIMDScalarDUPAlias<"dup", ".h",
8736                           !cast<Instruction>(NAME#"i16"),
8737                           FPR16, V128, VectorIndexH>;
8738  def : SIMDScalarDUPAlias<"dup", ".s",
8739                           !cast<Instruction>(NAME#"i32"),
8740                           FPR32, V128, VectorIndexS>;
8741  def : SIMDScalarDUPAlias<"dup", ".d",
8742                           !cast<Instruction>(NAME#"i64"),
8743                           FPR64, V128, VectorIndexD>;
8744}
8745
8746//----------------------------------------------------------------------------
8747// AdvSIMD modified immediate instructions
8748//----------------------------------------------------------------------------
8749
8750class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8751                          string asm, string op_string,
8752                          string cstr, list<dag> pattern>
8753  : I<oops, iops, asm, op_string, cstr, pattern>,
8754    Sched<[!if(Q, WriteVq, WriteVd)]> {
8755  bits<5> Rd;
8756  bits<8> imm8;
8757  let Inst{31}    = 0;
8758  let Inst{30}    = Q;
8759  let Inst{29}    = op;
8760  let Inst{28-19} = 0b0111100000;
8761  let Inst{18-16} = imm8{7-5};
8762  let Inst{11} = op2;
8763  let Inst{10} = 1;
8764  let Inst{9-5}   = imm8{4-0};
8765  let Inst{4-0}   = Rd;
8766}
8767
8768class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8769                                Operand immtype, dag opt_shift_iop,
8770                                string opt_shift, string asm, string kind,
8771                                list<dag> pattern>
8772  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8773                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8774                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8775                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8776                        "", pattern> {
8777  let DecoderMethod = "DecodeModImmInstruction";
8778}
8779
8780class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8781                                Operand immtype, dag opt_shift_iop,
8782                                string opt_shift, string asm, string kind,
8783                                list<dag> pattern>
8784  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8785                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8786                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8787                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8788                        "$Rd = $dst", pattern> {
8789  let DecoderMethod = "DecodeModImmTiedInstruction";
8790}
8791
8792class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8793                                     RegisterOperand vectype, string asm,
8794                                     string kind, list<dag> pattern>
8795  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8796                              (ins logical_vec_shift:$shift),
8797                              "$shift", asm, kind, pattern> {
8798  bits<2> shift;
8799  let Inst{15}    = b15_b12{1};
8800  let Inst{14-13} = shift;
8801  let Inst{12}    = b15_b12{0};
8802}
8803
8804class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8805                                     RegisterOperand vectype, string asm,
8806                                     string kind, list<dag> pattern>
8807  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8808                              (ins logical_vec_shift:$shift),
8809                              "$shift", asm, kind, pattern> {
8810  bits<2> shift;
8811  let Inst{15}    = b15_b12{1};
8812  let Inst{14-13} = shift;
8813  let Inst{12}    = b15_b12{0};
8814}
8815
8816
8817class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8818                                         RegisterOperand vectype, string asm,
8819                                         string kind, list<dag> pattern>
8820  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8821                              (ins logical_vec_hw_shift:$shift),
8822                              "$shift", asm, kind, pattern> {
8823  bits<2> shift;
8824  let Inst{15} = b15_b12{1};
8825  let Inst{14} = 0;
8826  let Inst{13} = shift{0};
8827  let Inst{12} = b15_b12{0};
8828}
8829
8830class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8831                                         RegisterOperand vectype, string asm,
8832                                         string kind, list<dag> pattern>
8833  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8834                              (ins logical_vec_hw_shift:$shift),
8835                              "$shift", asm, kind, pattern> {
8836  bits<2> shift;
8837  let Inst{15} = b15_b12{1};
8838  let Inst{14} = 0;
8839  let Inst{13} = shift{0};
8840  let Inst{12} = b15_b12{0};
8841}
8842
8843multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8844                                      string asm> {
8845  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8846                                                 asm, ".4h", []>;
8847  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8848                                                 asm, ".8h", []>;
8849
8850  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8851                                             asm, ".2s", []>;
8852  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8853                                             asm, ".4s", []>;
8854}
8855
8856multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8857                                      bits<2> w_cmode, string asm,
8858                                      SDNode OpNode> {
8859  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8860                                                 asm, ".4h",
8861             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8862                                             imm0_255:$imm8,
8863                                             (i32 imm:$shift)))]>;
8864  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8865                                                 asm, ".8h",
8866             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8867                                              imm0_255:$imm8,
8868                                              (i32 imm:$shift)))]>;
8869
8870  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8871                                             asm, ".2s",
8872             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8873                                             imm0_255:$imm8,
8874                                             (i32 imm:$shift)))]>;
8875  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8876                                             asm, ".4s",
8877             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8878                                              imm0_255:$imm8,
8879                                              (i32 imm:$shift)))]>;
8880}
8881
8882class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8883                             RegisterOperand vectype, string asm,
8884                             string kind, list<dag> pattern>
8885  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8886                              (ins move_vec_shift:$shift),
8887                              "$shift", asm, kind, pattern> {
8888  bits<1> shift;
8889  let Inst{15-13} = cmode{3-1};
8890  let Inst{12}    = shift;
8891}
8892
8893class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8894                                   RegisterOperand vectype,
8895                                   Operand imm_type, string asm,
8896                                   string kind, list<dag> pattern>
8897  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8898                              asm, kind, pattern> {
8899  let Inst{15-12} = cmode;
8900}
8901
8902class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8903                                   list<dag> pattern>
8904  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8905                        "\t$Rd, $imm8", "", pattern> {
8906  let Inst{15-12} = cmode;
8907  let DecoderMethod = "DecodeModImmInstruction";
8908}
8909
8910//----------------------------------------------------------------------------
8911// AdvSIMD indexed element
8912//----------------------------------------------------------------------------
8913
8914let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8915class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8916                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8917                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8918                      string apple_kind, string dst_kind, string lhs_kind,
8919                      string rhs_kind, list<dag> pattern>
8920  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8921      asm,
8922      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8923      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8924    Sched<[WriteVd]> {
8925  bits<5> Rd;
8926  bits<5> Rn;
8927  bits<5> Rm;
8928
8929  let Inst{31}    = 0;
8930  let Inst{30}    = Q;
8931  let Inst{29}    = U;
8932  let Inst{28}    = Scalar;
8933  let Inst{27-24} = 0b1111;
8934  let Inst{23-22} = size;
8935  // Bit 21 must be set by the derived class.
8936  let Inst{20-16} = Rm;
8937  let Inst{15-12} = opc;
8938  // Bit 11 must be set by the derived class.
8939  let Inst{10}    = 0;
8940  let Inst{9-5}   = Rn;
8941  let Inst{4-0}   = Rd;
8942}
8943
8944let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8945class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8946                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8947                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8948                      string apple_kind, string dst_kind, string lhs_kind,
8949                      string rhs_kind, list<dag> pattern>
8950  : I<(outs dst_reg:$dst),
8951      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8952      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8953      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8954    Sched<[WriteVd]> {
8955  bits<5> Rd;
8956  bits<5> Rn;
8957  bits<5> Rm;
8958
8959  let Inst{31}    = 0;
8960  let Inst{30}    = Q;
8961  let Inst{29}    = U;
8962  let Inst{28}    = Scalar;
8963  let Inst{27-24} = 0b1111;
8964  let Inst{23-22} = size;
8965  // Bit 21 must be set by the derived class.
8966  let Inst{20-16} = Rm;
8967  let Inst{15-12} = opc;
8968  // Bit 11 must be set by the derived class.
8969  let Inst{10}    = 0;
8970  let Inst{9-5}   = Rn;
8971  let Inst{4-0}   = Rd;
8972}
8973
8974
8975//----------------------------------------------------------------------------
8976// Armv8.6 BFloat16 Extension
8977//----------------------------------------------------------------------------
8978let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8979
8980class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8981                                   string kind2, RegisterOperand RegType,
8982                                   ValueType AccumType, ValueType InputType>
8983  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8984                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8985                                            (InputType RegType:$Rn),
8986                                            (InputType RegType:$Rm)))]> {
8987  let AsmString = !strconcat(asm,
8988                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8989                               ", $Rm" # kind2 # "}");
8990}
8991
8992multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8993  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8994                                           v2f32, v4bf16>;
8995  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8996                                           v4f32, v8bf16>;
8997}
8998
8999class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
9000                                      string dst_kind, string lhs_kind,
9001                                      string rhs_kind,
9002                                      RegisterOperand RegType,
9003                                      ValueType AccumType,
9004                                      ValueType InputType>
9005  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
9006                        RegType, RegType, V128, VectorIndexS,
9007                        asm, "", dst_kind, lhs_kind, rhs_kind,
9008        [(set (AccumType RegType:$dst),
9009              (AccumType (int_aarch64_neon_bfdot
9010                                 (AccumType RegType:$Rd),
9011                                 (InputType RegType:$Rn),
9012                                 (InputType (bitconvert (AccumType
9013                                    (AArch64duplane32 (v4f32 V128:$Rm),
9014                                        VectorIndexS:$idx)))))))]> {
9015
9016  bits<2> idx;
9017  let Inst{21}    = idx{0};  // L
9018  let Inst{11}    = idx{1};  // H
9019}
9020
9021multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
9022
9023  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
9024                                               ".2h", V64, v2f32, v4bf16>;
9025  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
9026                                              ".2h", V128, v4f32, v8bf16>;
9027}
9028
9029let mayRaiseFPException = 1, Uses = [FPCR] in
9030class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
9031  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
9032              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9033                                               (v8bf16 V128:$Rn),
9034                                               (v8bf16 V128:$Rm)))]> {
9035  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
9036}
9037
9038let mayRaiseFPException = 1, Uses = [FPCR] in
9039class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
9040  : I<(outs V128:$dst),
9041      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
9042      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
9043          [(set (v4f32 V128:$dst),
9044                (v4f32 (OpNode (v4f32 V128:$Rd),
9045                               (v8bf16 V128:$Rn),
9046                               (v8bf16
9047                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
9048                                      VectorIndexH:$idx)))))]>,
9049    Sched<[WriteVq]> {
9050  bits<5> Rd;
9051  bits<5> Rn;
9052  bits<4> Rm;
9053  bits<3> idx;
9054
9055  let Inst{31}    = 0;
9056  let Inst{30}    = Q;
9057  let Inst{29-22} = 0b00111111;
9058  let Inst{21-20} = idx{1-0};
9059  let Inst{19-16} = Rm;
9060  let Inst{15-12} = 0b1111;
9061  let Inst{11}    = idx{2};   // H
9062  let Inst{10}    = 0;
9063  let Inst{9-5}   = Rn;
9064  let Inst{4-0}   = Rd;
9065}
9066
9067class SIMDThreeSameVectorBF16MatrixMul<string asm>
9068  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
9069                                V128, asm, ".4s",
9070                          [(set (v4f32 V128:$dst),
9071                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
9072                                                         (v8bf16 V128:$Rn),
9073                                                         (v8bf16 V128:$Rm)))]> {
9074  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
9075                                    ", $Rm", ".8h", "}");
9076}
9077
9078let mayRaiseFPException = 1, Uses = [FPCR] in
9079class SIMD_BFCVTN
9080  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V64,
9081                           "bfcvtn", ".4h", ".4s",
9082    [(set (v4bf16 V64:$Rd), (any_fpround (v4f32 V128:$Rn)))]>;
9083
9084let mayRaiseFPException = 1, Uses = [FPCR] in
9085class SIMD_BFCVTN2
9086  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
9087                               "bfcvtn2", ".8h", ".4s", []>;
9088
9089let mayRaiseFPException = 1, Uses = [FPCR] in
9090class BF16ToSinglePrecision<string asm>
9091  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
9092    [(set (bf16 FPR16:$Rd), (any_fpround (f32 FPR32:$Rn)))]>,
9093    Sched<[WriteFCvt]> {
9094  bits<5> Rd;
9095  bits<5> Rn;
9096  let Inst{31-10} = 0b0001111001100011010000;
9097  let Inst{9-5}   = Rn;
9098  let Inst{4-0}   = Rd;
9099}
9100} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
9101
9102//----------------------------------------------------------------------------
9103class BaseSIMDThreeSameVectorIndexB<bit Q, bit U, bits<2> sz, bits<4> opc,
9104                                    string asm, string dst_kind,
9105                                    RegisterOperand RegType,
9106                                    RegisterOperand RegType_lo>
9107  : BaseSIMDIndexedTied<Q, U, 0b0, sz, opc,
9108                        RegType, RegType, RegType_lo, VectorIndexB32b_timm,
9109                        asm, "", dst_kind, ".16b", ".b", []> {
9110
9111  // idx = H:L:M
9112  bits<4> idx;
9113  let Inst{11}    = idx{3};
9114  let Inst{21-19} = idx{2-0};
9115}
9116
9117multiclass SIMDThreeSameVectorMLAIndex<bit Q, string asm, SDPatternOperator op> {
9118  let Uses = [FPMR, FPCR], mayLoad = 1 in {
9119    def v8f16 : BaseSIMDThreeSameVectorIndexB<Q, 0b0, 0b11, 0b0000, asm, ".8h",
9120                                              V128, V128_0to7>;
9121  }
9122
9123  def : Pat<(v8f16 (op (v8f16 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128_0to7:$Rm), VectorIndexB32b_timm:$Idx)),
9124            (!cast<Instruction>(NAME # v8f16) $Rd, $Rn, $Rm, $Idx)>;
9125}
9126
9127multiclass SIMDThreeSameVectorMLALIndex<bit Q, bits<2> sz, string asm, SDPatternOperator op> {
9128  let Uses = [FPMR, FPCR], mayLoad = 1 in {
9129    def v4f32 : BaseSIMDThreeSameVectorIndexB<Q, 0b1, sz, 0b1000, asm, ".4s",
9130                                              V128, V128_0to7>;
9131  }
9132
9133  def : Pat<(v4f32 (op (v4f32 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128_0to7:$Rm), VectorIndexB32b_timm:$Idx)),
9134            (!cast<Instruction>(NAME # v4f32) $Rd, $Rn, $Rm, $Idx)>;
9135}
9136
9137//----------------------------------------------------------------------------
9138// Armv8.6 Matrix Multiply Extension
9139//----------------------------------------------------------------------------
9140
9141class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
9142  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
9143              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
9144                                               (v16i8 V128:$Rn),
9145                                               (v16i8 V128:$Rm)))]> {
9146  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
9147}
9148
9149//----------------------------------------------------------------------------
9150// ARMv8.2-A Dot Product Instructions (Indexed)
9151class BaseSIMDThreeSameVectorIndexS<bit Q, bit U, bits<2> size, bits<4> opc, string asm,
9152                                    string dst_kind, string lhs_kind, string rhs_kind,
9153                                    RegisterOperand RegType,
9154                                    ValueType AccumType, ValueType InputType,
9155                                    AsmVectorIndexOpnd VIdx,
9156                                    SDPatternOperator OpNode> :
9157        BaseSIMDIndexedTied<Q, U, 0b0, size, opc, RegType, RegType, V128,
9158                            VIdx, asm, "", dst_kind, lhs_kind, rhs_kind,
9159        [(set (AccumType RegType:$dst),
9160              (AccumType (OpNode (AccumType RegType:$Rd),
9161                                 (InputType RegType:$Rn),
9162                                 (InputType (bitconvert (AccumType
9163                                    (AArch64duplane32 (v4i32 V128:$Rm),
9164                                        VIdx:$idx)))))))]> {
9165  bits<2> idx;
9166  let Inst{21}    = idx{0};  // L
9167  let Inst{11}    = idx{1};  // H
9168}
9169
9170multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
9171                                       SDPatternOperator OpNode> {
9172  def v8i8  : BaseSIMDThreeSameVectorIndexS<0, U, size, {0b111, Mixed}, asm, ".2s", ".8b", ".4b",
9173                                              V64, v2i32, v8i8, VectorIndexS, OpNode>;
9174  def v16i8 : BaseSIMDThreeSameVectorIndexS<1, U, size, {0b111, Mixed}, asm, ".4s", ".16b", ".4b",
9175                                              V128, v4i32, v16i8, VectorIndexS, OpNode>;
9176}
9177
9178multiclass SIMD_FP8_Dot4_Index<string asm, SDPatternOperator op> {
9179  let Uses = [FPMR, FPCR], mayLoad = 1 in {
9180    def v2f32 : BaseSIMDThreeSameVectorIndexS<0b0, 0b0, 0b00, 0b0000, asm, ".2s", ".8b", ".4b",
9181                                              V64, v2f32, v8i8, VectorIndexS32b_timm, null_frag>;
9182    def v4f32 : BaseSIMDThreeSameVectorIndexS<0b1, 0b0, 0b00, 0b0000, asm, ".4s", ".16b",".4b",
9183                                              V128, v4f32, v16i8, VectorIndexS32b_timm, null_frag>;
9184  }
9185
9186  def : Pat<(v2f32 (op (v2f32 V64:$Rd), (v8i8 V64:$Rn), (v16i8 V128:$Rm), VectorIndexS32b_timm:$Idx)),
9187            (!cast<Instruction>(NAME # v2f32) $Rd, $Rn, $Rm, $Idx)>;
9188
9189  def : Pat<(v4f32 (op (v4f32 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm), VectorIndexS32b_timm:$Idx)),
9190            (!cast<Instruction>(NAME # v4f32) $Rd, $Rn, $Rm, $Idx)>;
9191}
9192
9193// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
9194let mayRaiseFPException = 1, Uses = [FPCR] in
9195class BaseSIMDThreeSameVectorIndexH<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
9196                                      string dst_kind, string lhs_kind,
9197                                      string rhs_kind, RegisterOperand RegType,
9198                                      RegisterOperand RegType_lo, ValueType AccumType,
9199                                      ValueType InputType, AsmVectorIndexOpnd VIdx,
9200                                      SDPatternOperator OpNode> :
9201        BaseSIMDIndexedTied<Q, U, 0, sz, opc, RegType, RegType, RegType_lo,
9202                            VIdx, asm, "", dst_kind, lhs_kind, rhs_kind,
9203          [(set (AccumType RegType:$dst),
9204                (AccumType (OpNode (AccumType RegType:$Rd),
9205                                   (InputType RegType:$Rn),
9206                                   (InputType (AArch64duplane16 (v8f16 V128_lo:$Rm),
9207                                                VIdx:$idx)))))]> {
9208  // idx = H:L:M
9209  bits<3> idx;
9210  let Inst{11} = idx{2}; // H
9211  let Inst{21} = idx{1}; // L
9212  let Inst{20} = idx{0}; // M
9213}
9214
9215multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
9216                                       SDPatternOperator OpNode> {
9217  def v4f16 : BaseSIMDThreeSameVectorIndexH<0, U, 0b10, opc, asm, ".2s", ".2h", ".h",
9218                                              V64, V128_lo, v2f32, v4f16, VectorIndexH, OpNode>;
9219  def v8f16 : BaseSIMDThreeSameVectorIndexH<1, U, 0b10, opc, asm, ".4s", ".4h", ".h",
9220                                              V128, V128_lo, v4f32, v8f16, VectorIndexH, OpNode>;
9221}
9222
9223//----------------------------------------------------------------------------
9224// FP8 Advanced SIMD vector x indexed element
9225multiclass SIMD_FP8_Dot2_Index<string asm, SDPatternOperator op> {
9226  let Uses = [FPMR, FPCR], mayLoad = 1 in {
9227    def v4f16 : BaseSIMDThreeSameVectorIndexH<0b0, 0b0, 0b01, 0b0000, asm, ".4h", ".8b", ".2b",
9228                                              V64, V128_lo, v4f16, v8i8, VectorIndexH32b_timm, null_frag>;
9229    def v8f16 : BaseSIMDThreeSameVectorIndexH<0b1, 0b0, 0b01, 0b0000, asm, ".8h", ".16b", ".2b",
9230                                              V128, V128_lo, v8f16, v16i8, VectorIndexH32b_timm, null_frag>;
9231  }
9232  def : Pat<(v4f16 (op (v4f16 V64:$Rd), (v8i8 V64:$Rn), (v16i8 V128_lo:$Rm), VectorIndexH32b_timm:$Idx)),
9233            (!cast<Instruction>(NAME # v4f16) $Rd, $Rn, $Rm, $Idx)>;
9234
9235  def : Pat<(v8f16 (op (v8f16 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128_lo:$Rm), VectorIndexH32b_timm:$Idx)),
9236            (!cast<Instruction>(NAME # v8f16) $Rd, $Rn, $Rm, $Idx)>;
9237}
9238
9239multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
9240                         SDPatternOperator OpNode> {
9241  let mayRaiseFPException = 1, Uses = [FPCR] in {
9242  let Predicates = [HasNEON, HasFullFP16] in {
9243  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
9244                                      V64, V64,
9245                                      V128_lo, VectorIndexH,
9246                                      asm, ".4h", ".4h", ".4h", ".h",
9247    [(set (v4f16 V64:$Rd),
9248        (OpNode (v4f16 V64:$Rn),
9249         (dup_v8f16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9250    bits<3> idx;
9251    let Inst{11} = idx{2};
9252    let Inst{21} = idx{1};
9253    let Inst{20} = idx{0};
9254  }
9255
9256  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
9257                                      V128, V128,
9258                                      V128_lo, VectorIndexH,
9259                                      asm, ".8h", ".8h", ".8h", ".h",
9260    [(set (v8f16 V128:$Rd),
9261        (OpNode (v8f16 V128:$Rn),
9262         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9263    bits<3> idx;
9264    let Inst{11} = idx{2};
9265    let Inst{21} = idx{1};
9266    let Inst{20} = idx{0};
9267  }
9268  } // Predicates = [HasNEON, HasFullFP16]
9269
9270  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9271                                      V64, V64,
9272                                      V128, VectorIndexS,
9273                                      asm, ".2s", ".2s", ".2s", ".s",
9274    [(set (v2f32 V64:$Rd),
9275        (OpNode (v2f32 V64:$Rn),
9276         (dup_v4f32 (v4f32 V128:$Rm), VectorIndexS:$idx)))]> {
9277    bits<2> idx;
9278    let Inst{11} = idx{1};
9279    let Inst{21} = idx{0};
9280  }
9281
9282  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9283                                      V128, V128,
9284                                      V128, VectorIndexS,
9285                                      asm, ".4s", ".4s", ".4s", ".s",
9286    [(set (v4f32 V128:$Rd),
9287        (OpNode (v4f32 V128:$Rn),
9288         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
9289    bits<2> idx;
9290    let Inst{11} = idx{1};
9291    let Inst{21} = idx{0};
9292  }
9293
9294  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
9295                                      V128, V128,
9296                                      V128, VectorIndexD,
9297                                      asm, ".2d", ".2d", ".2d", ".d",
9298    [(set (v2f64 V128:$Rd),
9299        (OpNode (v2f64 V128:$Rn),
9300         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
9301    bits<1> idx;
9302    let Inst{11} = idx{0};
9303    let Inst{21} = 0;
9304  }
9305
9306  let Predicates = [HasNEON, HasFullFP16] in {
9307  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
9308                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9309                                      asm, ".h", "", "", ".h",
9310    [(set (f16 FPR16Op:$Rd),
9311          (OpNode (f16 FPR16Op:$Rn),
9312                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
9313                                       VectorIndexH:$idx))))]> {
9314    bits<3> idx;
9315    let Inst{11} = idx{2};
9316    let Inst{21} = idx{1};
9317    let Inst{20} = idx{0};
9318  }
9319  } // Predicates = [HasNEON, HasFullFP16]
9320
9321  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9322                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9323                                      asm, ".s", "", "", ".s",
9324    [(set (f32 FPR32Op:$Rd),
9325          (OpNode (f32 FPR32Op:$Rn),
9326                  (f32 (vector_extract (v4f32 V128:$Rm),
9327                                       VectorIndexS:$idx))))]> {
9328    bits<2> idx;
9329    let Inst{11} = idx{1};
9330    let Inst{21} = idx{0};
9331  }
9332
9333  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
9334                                      FPR64Op, FPR64Op, V128, VectorIndexD,
9335                                      asm, ".d", "", "", ".d",
9336    [(set (f64 FPR64Op:$Rd),
9337          (OpNode (f64 FPR64Op:$Rn),
9338                  (f64 (vector_extract (v2f64 V128:$Rm),
9339                                       VectorIndexD:$idx))))]> {
9340    bits<1> idx;
9341    let Inst{11} = idx{0};
9342    let Inst{21} = 0;
9343  }
9344  } // mayRaiseFPException = 1, Uses = [FPCR]
9345
9346  let Predicates = [HasNEON, HasFullFP16] in {
9347  def : Pat<(f16 (OpNode
9348                   (f16 (vector_extract (v8f16 V128:$Rn), (i64 0))),
9349                   (f16 (vector_extract (v8f16 V128:$Rm), VectorIndexH:$idx)))),
9350            (!cast<Instruction>(NAME # v1i16_indexed)
9351              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), V128:$Rm, VectorIndexH:$idx)>;
9352  }
9353
9354  let Predicates = [HasNEON] in {
9355  def : Pat<(f32 (OpNode
9356                   (f32 (vector_extract (v4f32 V128:$Rn), (i64 0))),
9357                   (f32 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx)))),
9358            (!cast<Instruction>(NAME # v1i32_indexed)
9359              (EXTRACT_SUBREG V128:$Rn, ssub), V128:$Rm, VectorIndexS:$idx)>;
9360
9361  def : Pat<(f64 (OpNode
9362                   (f64 (vector_extract (v2f64 V128:$Rn), (i64 0))),
9363                   (f64 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx)))),
9364            (!cast<Instruction>(NAME # v1i64_indexed)
9365              (EXTRACT_SUBREG V128:$Rn, dsub), V128:$Rm, VectorIndexD:$idx)>;
9366  }
9367}
9368
9369multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
9370  let Predicates = [HasNEON, HasFullFP16] in {
9371  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
9372  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
9373                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
9374                                           VectorIndexH:$idx))),
9375            (!cast<Instruction>(INST # "v8i16_indexed")
9376                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
9377  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
9378                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
9379            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
9380                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
9381
9382  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
9383                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
9384                                           VectorIndexH:$idx))),
9385            (!cast<Instruction>(INST # "v4i16_indexed")
9386                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
9387  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
9388                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
9389            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
9390                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
9391
9392  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
9393                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
9394            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
9395                V128_lo:$Rm, VectorIndexH:$idx)>;
9396  def : Pat<(f16 (OpNode (f16 FPR16:$Rd),
9397                         (vector_extract (v8f16 V128:$Rn), (i64 0)),
9398                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
9399            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd,
9400                (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), V128_lo:$Rm, VectorIndexH:$idx)>;
9401  } // Predicates = [HasNEON, HasFullFP16]
9402
9403  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
9404  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
9405                           (AArch64duplane32 (v4f32 V128:$Rm),
9406                                           VectorIndexS:$idx))),
9407            (!cast<Instruction>(INST # v2i32_indexed)
9408                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
9409  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
9410                           (AArch64dup (f32 FPR32Op:$Rm)))),
9411            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
9412                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
9413
9414
9415  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
9416  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
9417                           (AArch64duplane32 (v4f32 V128:$Rm),
9418                                           VectorIndexS:$idx))),
9419            (!cast<Instruction>(INST # "v4i32_indexed")
9420                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
9421  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
9422                           (AArch64dup (f32 FPR32Op:$Rm)))),
9423            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
9424                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
9425
9426  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
9427  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
9428                           (AArch64duplane64 (v2f64 V128:$Rm),
9429                                           VectorIndexD:$idx))),
9430            (!cast<Instruction>(INST # "v2i64_indexed")
9431                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
9432  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
9433                           (AArch64dup (f64 FPR64Op:$Rm)))),
9434            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
9435                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
9436
9437  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
9438  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
9439                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
9440            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
9441                V128:$Rm, VectorIndexS:$idx)>;
9442  def : Pat<(f32 (OpNode (f32 FPR32:$Rd),
9443                         (vector_extract (v4f32 V128:$Rn), (i64 0)),
9444                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
9445            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd,
9446                (f32 (EXTRACT_SUBREG V128:$Rn, ssub)), V128:$Rm, VectorIndexS:$idx)>;
9447
9448  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
9449  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
9450                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
9451            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
9452                V128:$Rm, VectorIndexD:$idx)>;
9453  def : Pat<(f64 (OpNode (f64 FPR64:$Rd),
9454                         (vector_extract (v2f64 V128:$Rn), (i64 0)),
9455                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
9456            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd,
9457                (f64 (EXTRACT_SUBREG V128:$Rn, dsub)), V128:$Rm, VectorIndexD:$idx)>;
9458}
9459
9460let mayRaiseFPException = 1, Uses = [FPCR] in
9461multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
9462  let Predicates = [HasNEON, HasFullFP16] in {
9463  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
9464                                          V128_lo, VectorIndexH,
9465                                          asm, ".4h", ".4h", ".4h", ".h", []> {
9466    bits<3> idx;
9467    let Inst{11} = idx{2};
9468    let Inst{21} = idx{1};
9469    let Inst{20} = idx{0};
9470  }
9471
9472  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
9473                                          V128, V128,
9474                                          V128_lo, VectorIndexH,
9475                                          asm, ".8h", ".8h", ".8h", ".h", []> {
9476    bits<3> idx;
9477    let Inst{11} = idx{2};
9478    let Inst{21} = idx{1};
9479    let Inst{20} = idx{0};
9480  }
9481  } // Predicates = [HasNEON, HasFullFP16]
9482
9483  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
9484                                          V128, VectorIndexS,
9485                                          asm, ".2s", ".2s", ".2s", ".s", []> {
9486    bits<2> idx;
9487    let Inst{11} = idx{1};
9488    let Inst{21} = idx{0};
9489  }
9490
9491  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9492                                      V128, V128,
9493                                      V128, VectorIndexS,
9494                                      asm, ".4s", ".4s", ".4s", ".s", []> {
9495    bits<2> idx;
9496    let Inst{11} = idx{1};
9497    let Inst{21} = idx{0};
9498  }
9499
9500  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
9501                                      V128, V128,
9502                                      V128, VectorIndexD,
9503                                      asm, ".2d", ".2d", ".2d", ".d", []> {
9504    bits<1> idx;
9505    let Inst{11} = idx{0};
9506    let Inst{21} = 0;
9507  }
9508
9509  let Predicates = [HasNEON, HasFullFP16] in {
9510  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
9511                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9512                                      asm, ".h", "", "", ".h", []> {
9513    bits<3> idx;
9514    let Inst{11} = idx{2};
9515    let Inst{21} = idx{1};
9516    let Inst{20} = idx{0};
9517  }
9518  } // Predicates = [HasNEON, HasFullFP16]
9519
9520  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9521                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9522                                      asm, ".s", "", "", ".s", []> {
9523    bits<2> idx;
9524    let Inst{11} = idx{1};
9525    let Inst{21} = idx{0};
9526  }
9527
9528  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
9529                                      FPR64Op, FPR64Op, V128, VectorIndexD,
9530                                      asm, ".d", "", "", ".d", []> {
9531    bits<1> idx;
9532    let Inst{11} = idx{0};
9533    let Inst{21} = 0;
9534  }
9535}
9536
9537multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
9538                                 SDPatternOperator OpNodeLaneQ> {
9539
9540  def : Pat<(v4i16 (OpNodeLane
9541                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
9542                     VectorIndexS32b:$idx)),
9543            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
9544              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
9545              (UImmS1XForm $idx))>;
9546
9547  def : Pat<(v4i16 (OpNodeLaneQ
9548                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
9549                     VectorIndexH32b:$idx)),
9550            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
9551              (UImmS1XForm $idx))>;
9552
9553  def : Pat<(v8i16 (OpNodeLane
9554                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
9555                     VectorIndexS32b:$idx)),
9556            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
9557              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9558              (UImmS1XForm $idx))>;
9559
9560  def : Pat<(v8i16 (OpNodeLaneQ
9561                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
9562                     VectorIndexH32b:$idx)),
9563            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
9564              (UImmS1XForm $idx))>;
9565
9566  def : Pat<(v2i32 (OpNodeLane
9567                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
9568                     VectorIndexD32b:$idx)),
9569            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
9570              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
9571              (UImmS1XForm $idx))>;
9572
9573  def : Pat<(v2i32 (OpNodeLaneQ
9574                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
9575                     VectorIndexS32b:$idx)),
9576            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
9577              (UImmS1XForm $idx))>;
9578
9579  def : Pat<(v4i32 (OpNodeLane
9580                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
9581                     VectorIndexD32b:$idx)),
9582            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
9583              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9584              (UImmS1XForm $idx))>;
9585
9586  def : Pat<(v4i32 (OpNodeLaneQ
9587                     (v4i32 V128:$Rn),
9588                     (v4i32 V128:$Rm),
9589                     VectorIndexS32b:$idx)),
9590            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
9591              (UImmS1XForm $idx))>;
9592
9593}
9594
9595multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
9596                         SDPatternOperator OpNode> {
9597  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
9598                                      V128_lo, VectorIndexH,
9599                                      asm, ".4h", ".4h", ".4h", ".h",
9600    [(set (v4i16 V64:$Rd),
9601        (OpNode (v4i16 V64:$Rn),
9602         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9603    bits<3> idx;
9604    let Inst{11} = idx{2};
9605    let Inst{21} = idx{1};
9606    let Inst{20} = idx{0};
9607  }
9608
9609  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9610                                      V128, V128,
9611                                      V128_lo, VectorIndexH,
9612                                      asm, ".8h", ".8h", ".8h", ".h",
9613    [(set (v8i16 V128:$Rd),
9614       (OpNode (v8i16 V128:$Rn),
9615         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9616    bits<3> idx;
9617    let Inst{11} = idx{2};
9618    let Inst{21} = idx{1};
9619    let Inst{20} = idx{0};
9620  }
9621
9622  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9623                                      V64, V64,
9624                                      V128, VectorIndexS,
9625                                      asm, ".2s", ".2s", ".2s",  ".s",
9626    [(set (v2i32 V64:$Rd),
9627       (OpNode (v2i32 V64:$Rn),
9628          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9629    bits<2> idx;
9630    let Inst{11} = idx{1};
9631    let Inst{21} = idx{0};
9632  }
9633
9634  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9635                                      V128, V128,
9636                                      V128, VectorIndexS,
9637                                      asm, ".4s", ".4s", ".4s", ".s",
9638    [(set (v4i32 V128:$Rd),
9639       (OpNode (v4i32 V128:$Rn),
9640          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9641    bits<2> idx;
9642    let Inst{11} = idx{1};
9643    let Inst{21} = idx{0};
9644  }
9645
9646  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9647                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9648                                      asm, ".h", "", "", ".h", []> {
9649    bits<3> idx;
9650    let Inst{11} = idx{2};
9651    let Inst{21} = idx{1};
9652    let Inst{20} = idx{0};
9653  }
9654
9655  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9656                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9657                                      asm, ".s", "", "", ".s",
9658      [(set (i32 FPR32Op:$Rd),
9659            (OpNode FPR32Op:$Rn,
9660                    (i32 (vector_extract (v4i32 V128:$Rm),
9661                                         VectorIndexS:$idx))))]> {
9662    bits<2> idx;
9663    let Inst{11} = idx{1};
9664    let Inst{21} = idx{0};
9665  }
9666}
9667
9668multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
9669                               SDPatternOperator OpNode> {
9670  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9671                                      V64, V64,
9672                                      V128_lo, VectorIndexH,
9673                                      asm, ".4h", ".4h", ".4h", ".h",
9674    [(set (v4i16 V64:$Rd),
9675        (OpNode (v4i16 V64:$Rn),
9676         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9677    bits<3> idx;
9678    let Inst{11} = idx{2};
9679    let Inst{21} = idx{1};
9680    let Inst{20} = idx{0};
9681  }
9682
9683  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9684                                      V128, V128,
9685                                      V128_lo, VectorIndexH,
9686                                      asm, ".8h", ".8h", ".8h", ".h",
9687    [(set (v8i16 V128:$Rd),
9688       (OpNode (v8i16 V128:$Rn),
9689         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9690    bits<3> idx;
9691    let Inst{11} = idx{2};
9692    let Inst{21} = idx{1};
9693    let Inst{20} = idx{0};
9694  }
9695
9696  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9697                                      V64, V64,
9698                                      V128, VectorIndexS,
9699                                      asm, ".2s", ".2s", ".2s", ".s",
9700    [(set (v2i32 V64:$Rd),
9701       (OpNode (v2i32 V64:$Rn),
9702          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9703    bits<2> idx;
9704    let Inst{11} = idx{1};
9705    let Inst{21} = idx{0};
9706  }
9707
9708  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9709                                      V128, V128,
9710                                      V128, VectorIndexS,
9711                                      asm, ".4s", ".4s", ".4s", ".s",
9712    [(set (v4i32 V128:$Rd),
9713       (OpNode (v4i32 V128:$Rn),
9714          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9715    bits<2> idx;
9716    let Inst{11} = idx{1};
9717    let Inst{21} = idx{0};
9718  }
9719}
9720
9721multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
9722                                   SDPatternOperator OpNode> {
9723  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
9724                                          V128_lo, VectorIndexH,
9725                                          asm, ".4h", ".4h", ".4h", ".h",
9726    [(set (v4i16 V64:$dst),
9727        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
9728         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9729    bits<3> idx;
9730    let Inst{11} = idx{2};
9731    let Inst{21} = idx{1};
9732    let Inst{20} = idx{0};
9733  }
9734
9735  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9736                                      V128, V128,
9737                                      V128_lo, VectorIndexH,
9738                                      asm, ".8h", ".8h", ".8h", ".h",
9739    [(set (v8i16 V128:$dst),
9740       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9741         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9742    bits<3> idx;
9743    let Inst{11} = idx{2};
9744    let Inst{21} = idx{1};
9745    let Inst{20} = idx{0};
9746  }
9747
9748  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9749                                      V64, V64,
9750                                      V128, VectorIndexS,
9751                                      asm, ".2s", ".2s", ".2s", ".s",
9752    [(set (v2i32 V64:$dst),
9753       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9754          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9755    bits<2> idx;
9756    let Inst{11} = idx{1};
9757    let Inst{21} = idx{0};
9758  }
9759
9760  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9761                                      V128, V128,
9762                                      V128, VectorIndexS,
9763                                      asm, ".4s", ".4s", ".4s", ".s",
9764    [(set (v4i32 V128:$dst),
9765       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9766          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9767    bits<2> idx;
9768    let Inst{11} = idx{1};
9769    let Inst{21} = idx{0};
9770  }
9771}
9772
9773multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
9774                             SDPatternOperator OpNode> {
9775  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9776                                      V128, V64,
9777                                      V128_lo, VectorIndexH,
9778                                      asm, ".4s", ".4s", ".4h", ".h",
9779    [(set (v4i32 V128:$Rd),
9780        (OpNode (v4i16 V64:$Rn),
9781         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9782    bits<3> idx;
9783    let Inst{11} = idx{2};
9784    let Inst{21} = idx{1};
9785    let Inst{20} = idx{0};
9786  }
9787
9788  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9789                                      V128, V128,
9790                                      V128_lo, VectorIndexH,
9791                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9792    [(set (v4i32 V128:$Rd),
9793          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9794                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9795
9796    bits<3> idx;
9797    let Inst{11} = idx{2};
9798    let Inst{21} = idx{1};
9799    let Inst{20} = idx{0};
9800  }
9801
9802  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9803                                      V128, V64,
9804                                      V128, VectorIndexS,
9805                                      asm, ".2d", ".2d", ".2s", ".s",
9806    [(set (v2i64 V128:$Rd),
9807        (OpNode (v2i32 V64:$Rn),
9808         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9809    bits<2> idx;
9810    let Inst{11} = idx{1};
9811    let Inst{21} = idx{0};
9812  }
9813
9814  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9815                                      V128, V128,
9816                                      V128, VectorIndexS,
9817                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9818    [(set (v2i64 V128:$Rd),
9819          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9820                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9821    bits<2> idx;
9822    let Inst{11} = idx{1};
9823    let Inst{21} = idx{0};
9824  }
9825
9826  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9827                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9828                                      asm, ".h", "", "", ".h", []> {
9829    bits<3> idx;
9830    let Inst{11} = idx{2};
9831    let Inst{21} = idx{1};
9832    let Inst{20} = idx{0};
9833  }
9834
9835  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9836                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9837                                      asm, ".s", "", "", ".s", []> {
9838    bits<2> idx;
9839    let Inst{11} = idx{1};
9840    let Inst{21} = idx{0};
9841  }
9842}
9843
9844multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
9845                                       SDPatternOperator Accum> {
9846  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9847                                      V128, V64,
9848                                      V128_lo, VectorIndexH,
9849                                      asm, ".4s", ".4s", ".4h", ".h",
9850    [(set (v4i32 V128:$dst),
9851          (Accum (v4i32 V128:$Rd),
9852                 (v4i32 (int_aarch64_neon_sqdmull
9853                             (v4i16 V64:$Rn),
9854                             (dup_v8i16 (v8i16 V128_lo:$Rm),
9855                                         VectorIndexH:$idx)))))]> {
9856    bits<3> idx;
9857    let Inst{11} = idx{2};
9858    let Inst{21} = idx{1};
9859    let Inst{20} = idx{0};
9860  }
9861
9862  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9863                                      V128, V128,
9864                                      V128_lo, VectorIndexH,
9865                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9866    [(set (v4i32 V128:$dst),
9867          (Accum (v4i32 V128:$Rd),
9868                 (v4i32 (int_aarch64_neon_sqdmull
9869                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9870                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9871    bits<3> idx;
9872    let Inst{11} = idx{2};
9873    let Inst{21} = idx{1};
9874    let Inst{20} = idx{0};
9875  }
9876
9877  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9878                                      V128, V64,
9879                                      V128, VectorIndexS,
9880                                      asm, ".2d", ".2d", ".2s", ".s",
9881    [(set (v2i64 V128:$dst),
9882        (Accum (v2i64 V128:$Rd),
9883               (v2i64 (int_aarch64_neon_sqdmull
9884                          (v2i32 V64:$Rn),
9885                          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9886    bits<2> idx;
9887    let Inst{11} = idx{1};
9888    let Inst{21} = idx{0};
9889  }
9890
9891  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9892                                      V128, V128,
9893                                      V128, VectorIndexS,
9894                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9895    [(set (v2i64 V128:$dst),
9896          (Accum (v2i64 V128:$Rd),
9897                 (v2i64 (int_aarch64_neon_sqdmull
9898                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9899                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9900    bits<2> idx;
9901    let Inst{11} = idx{1};
9902    let Inst{21} = idx{0};
9903  }
9904
9905  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9906                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9907                                      asm, ".h", "", "", ".h", []> {
9908    bits<3> idx;
9909    let Inst{11} = idx{2};
9910    let Inst{21} = idx{1};
9911    let Inst{20} = idx{0};
9912  }
9913
9914  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9915                        (i32 (vector_extract
9916                                    (v4i32 (int_aarch64_neon_sqdmull
9917                                                (v4i16 V64:$Rn),
9918                                                (v4i16 V64:$Rm))),
9919                                    (i64 0))))),
9920            (!cast<Instruction>(NAME # v1i32_indexed)
9921                        FPR32Op:$Rd,
9922                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9923                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9924                        (i64 0))>;
9925
9926  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9927                        (i32 (vector_extract
9928                                    (v4i32 (int_aarch64_neon_sqdmull
9929                                                (v4i16 V64:$Rn),
9930                                                (dup_v8i16 (v8i16 V128_lo:$Rm),
9931                                                            VectorIndexH:$idx))),
9932                                    (i64 0))))),
9933            (!cast<Instruction>(NAME # v1i32_indexed)
9934                        FPR32Op:$Rd,
9935                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9936                        V128_lo:$Rm,
9937                        VectorIndexH:$idx)>;
9938
9939  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9940                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9941                                      asm, ".s", "", "", ".s",
9942    [(set (i64 FPR64Op:$dst),
9943          (Accum (i64 FPR64Op:$Rd),
9944                 (i64 (int_aarch64_neon_sqdmulls_scalar
9945                            (i32 FPR32Op:$Rn),
9946                            (i32 (vector_extract (v4i32 V128:$Rm),
9947                                                 VectorIndexS:$idx))))))]> {
9948
9949    bits<2> idx;
9950    let Inst{11} = idx{1};
9951    let Inst{21} = idx{0};
9952  }
9953}
9954
9955multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9956                                   SDPatternOperator OpNode> {
9957  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9958  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9959                                      V128, V64,
9960                                      V128_lo, VectorIndexH,
9961                                      asm, ".4s", ".4s", ".4h", ".h",
9962    [(set (v4i32 V128:$Rd),
9963        (OpNode (v4i16 V64:$Rn),
9964         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9965    bits<3> idx;
9966    let Inst{11} = idx{2};
9967    let Inst{21} = idx{1};
9968    let Inst{20} = idx{0};
9969  }
9970
9971  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9972                                      V128, V128,
9973                                      V128_lo, VectorIndexH,
9974                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9975    [(set (v4i32 V128:$Rd),
9976          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9977                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9978
9979    bits<3> idx;
9980    let Inst{11} = idx{2};
9981    let Inst{21} = idx{1};
9982    let Inst{20} = idx{0};
9983  }
9984
9985  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9986                                      V128, V64,
9987                                      V128, VectorIndexS,
9988                                      asm, ".2d", ".2d", ".2s", ".s",
9989    [(set (v2i64 V128:$Rd),
9990        (OpNode (v2i32 V64:$Rn),
9991         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9992    bits<2> idx;
9993    let Inst{11} = idx{1};
9994    let Inst{21} = idx{0};
9995  }
9996
9997  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9998                                      V128, V128,
9999                                      V128, VectorIndexS,
10000                                      asm#"2", ".2d", ".2d", ".4s", ".s",
10001    [(set (v2i64 V128:$Rd),
10002          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
10003                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
10004    bits<2> idx;
10005    let Inst{11} = idx{1};
10006    let Inst{21} = idx{0};
10007  }
10008  }
10009}
10010
10011multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
10012                                       SDPatternOperator OpNode> {
10013  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
10014  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10015                                      V128, V64,
10016                                      V128_lo, VectorIndexH,
10017                                      asm, ".4s", ".4s", ".4h", ".h",
10018    [(set (v4i32 V128:$dst),
10019        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
10020         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
10021    bits<3> idx;
10022    let Inst{11} = idx{2};
10023    let Inst{21} = idx{1};
10024    let Inst{20} = idx{0};
10025  }
10026
10027  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10028                                      V128, V128,
10029                                      V128_lo, VectorIndexH,
10030                                      asm#"2", ".4s", ".4s", ".8h", ".h",
10031    [(set (v4i32 V128:$dst),
10032          (OpNode (v4i32 V128:$Rd),
10033                  (extract_high_v8i16 (v8i16 V128:$Rn)),
10034                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
10035    bits<3> idx;
10036    let Inst{11} = idx{2};
10037    let Inst{21} = idx{1};
10038    let Inst{20} = idx{0};
10039  }
10040
10041  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10042                                      V128, V64,
10043                                      V128, VectorIndexS,
10044                                      asm, ".2d", ".2d", ".2s", ".s",
10045    [(set (v2i64 V128:$dst),
10046        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
10047         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
10048    bits<2> idx;
10049    let Inst{11} = idx{1};
10050    let Inst{21} = idx{0};
10051  }
10052
10053  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10054                                      V128, V128,
10055                                      V128, VectorIndexS,
10056                                      asm#"2", ".2d", ".2d", ".4s", ".s",
10057    [(set (v2i64 V128:$dst),
10058          (OpNode (v2i64 V128:$Rd),
10059                  (extract_high_v4i32 (v4i32 V128:$Rn)),
10060                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
10061    bits<2> idx;
10062    let Inst{11} = idx{1};
10063    let Inst{21} = idx{0};
10064  }
10065  }
10066}
10067
10068//----------------------------------------------------------------------------
10069// AdvSIMD scalar shift by immediate
10070//----------------------------------------------------------------------------
10071
10072let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10073class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
10074                     RegisterClass regtype1, RegisterClass regtype2,
10075                     Operand immtype, string asm, list<dag> pattern>
10076  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
10077      asm, "\t$Rd, $Rn, $imm", "", pattern>,
10078    Sched<[WriteVd]> {
10079  bits<5> Rd;
10080  bits<5> Rn;
10081  bits<7> imm;
10082  let Inst{31-30} = 0b01;
10083  let Inst{29}    = U;
10084  let Inst{28-23} = 0b111110;
10085  let Inst{22-16} = fixed_imm;
10086  let Inst{15-11} = opc;
10087  let Inst{10}    = 1;
10088  let Inst{9-5} = Rn;
10089  let Inst{4-0} = Rd;
10090}
10091
10092let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10093class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
10094                     RegisterClass regtype1, RegisterClass regtype2,
10095                     Operand immtype, string asm, list<dag> pattern>
10096  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
10097      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
10098    Sched<[WriteVd]> {
10099  bits<5> Rd;
10100  bits<5> Rn;
10101  bits<7> imm;
10102  let Inst{31-30} = 0b01;
10103  let Inst{29}    = U;
10104  let Inst{28-23} = 0b111110;
10105  let Inst{22-16} = fixed_imm;
10106  let Inst{15-11} = opc;
10107  let Inst{10}    = 1;
10108  let Inst{9-5} = Rn;
10109  let Inst{4-0} = Rd;
10110}
10111
10112
10113multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
10114  let Predicates = [HasNEON, HasFullFP16] in {
10115  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
10116                              FPR16, FPR16, vecshiftR16, asm, []> {
10117    let Inst{19-16} = imm{3-0};
10118  }
10119  } // Predicates = [HasNEON, HasFullFP16]
10120  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
10121                              FPR32, FPR32, vecshiftR32, asm, []> {
10122    let Inst{20-16} = imm{4-0};
10123  }
10124  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
10125                              FPR64, FPR64, vecshiftR64, asm, []> {
10126    let Inst{21-16} = imm{5-0};
10127  }
10128}
10129
10130multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
10131                             SDPatternOperator OpNode> {
10132  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
10133                              FPR64, FPR64, vecshiftR64, asm,
10134  [(set (i64 FPR64:$Rd),
10135     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
10136    let Inst{21-16} = imm{5-0};
10137  }
10138
10139  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
10140            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
10141}
10142
10143multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
10144                                 SDPatternOperator OpNode = null_frag> {
10145  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
10146                              FPR64, FPR64, vecshiftR64, asm,
10147  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
10148                                                   (i32 vecshiftR64:$imm)))]> {
10149    let Inst{21-16} = imm{5-0};
10150  }
10151
10152  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
10153                           (i32 vecshiftR64:$imm))),
10154            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
10155                                            vecshiftR64:$imm)>;
10156}
10157
10158multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
10159                             SDPatternOperator OpNode> {
10160  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
10161                              FPR64, FPR64, vecshiftL64, asm,
10162    [(set (i64 FPR64:$Rd),
10163       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
10164    let Inst{21-16} = imm{5-0};
10165  }
10166
10167  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
10168            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
10169}
10170
10171let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10172multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
10173  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
10174                              FPR64, FPR64, vecshiftL64, asm, []> {
10175    let Inst{21-16} = imm{5-0};
10176  }
10177}
10178
10179let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10180multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
10181                               SDPatternOperator OpNode = null_frag> {
10182  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
10183                              FPR8, FPR16, vecshiftR8, asm, []> {
10184    let Inst{18-16} = imm{2-0};
10185  }
10186
10187  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
10188                              FPR16, FPR32, vecshiftR16, asm, []> {
10189    let Inst{19-16} = imm{3-0};
10190  }
10191
10192  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
10193                              FPR32, FPR64, vecshiftR32, asm,
10194    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
10195    let Inst{20-16} = imm{4-0};
10196  }
10197}
10198
10199multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
10200                                SDPatternOperator OpNode> {
10201  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
10202                              FPR8, FPR8, vecshiftL8, asm, []> {
10203    let Inst{18-16} = imm{2-0};
10204  }
10205
10206  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
10207                              FPR16, FPR16, vecshiftL16, asm, []> {
10208    let Inst{19-16} = imm{3-0};
10209  }
10210
10211  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
10212                              FPR32, FPR32, vecshiftL32, asm,
10213    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
10214    let Inst{20-16} = imm{4-0};
10215  }
10216
10217  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
10218                              FPR64, FPR64, vecshiftL64, asm,
10219    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
10220    let Inst{21-16} = imm{5-0};
10221  }
10222
10223  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
10224            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
10225}
10226
10227multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
10228  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
10229                              FPR8, FPR8, vecshiftR8, asm, []> {
10230    let Inst{18-16} = imm{2-0};
10231  }
10232
10233  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
10234                              FPR16, FPR16, vecshiftR16, asm, []> {
10235    let Inst{19-16} = imm{3-0};
10236  }
10237
10238  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
10239                              FPR32, FPR32, vecshiftR32, asm, []> {
10240    let Inst{20-16} = imm{4-0};
10241  }
10242
10243  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
10244                              FPR64, FPR64, vecshiftR64, asm, []> {
10245    let Inst{21-16} = imm{5-0};
10246  }
10247}
10248
10249//----------------------------------------------------------------------------
10250// AdvSIMD vector x indexed element
10251//----------------------------------------------------------------------------
10252
10253let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10254class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
10255                     RegisterOperand dst_reg, RegisterOperand src_reg,
10256                     Operand immtype,
10257                     string asm, string dst_kind, string src_kind,
10258                     list<dag> pattern>
10259  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
10260      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
10261           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
10262    Sched<[!if(Q, WriteVq, WriteVd)]> {
10263  bits<5> Rd;
10264  bits<5> Rn;
10265  let Inst{31}    = 0;
10266  let Inst{30}    = Q;
10267  let Inst{29}    = U;
10268  let Inst{28-23} = 0b011110;
10269  let Inst{22-16} = fixed_imm;
10270  let Inst{15-11} = opc;
10271  let Inst{10}    = 1;
10272  let Inst{9-5}   = Rn;
10273  let Inst{4-0}   = Rd;
10274}
10275
10276let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
10277class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
10278                     RegisterOperand vectype1, RegisterOperand vectype2,
10279                     Operand immtype,
10280                     string asm, string dst_kind, string src_kind,
10281                     list<dag> pattern>
10282  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
10283      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
10284           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
10285    Sched<[!if(Q, WriteVq, WriteVd)]> {
10286  bits<5> Rd;
10287  bits<5> Rn;
10288  let Inst{31}    = 0;
10289  let Inst{30}    = Q;
10290  let Inst{29}    = U;
10291  let Inst{28-23} = 0b011110;
10292  let Inst{22-16} = fixed_imm;
10293  let Inst{15-11} = opc;
10294  let Inst{10}    = 1;
10295  let Inst{9-5}   = Rn;
10296  let Inst{4-0}   = Rd;
10297}
10298
10299multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
10300                              Intrinsic OpNode> {
10301  let Predicates = [HasNEON, HasFullFP16] in {
10302  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10303                                  V64, V64, vecshiftR16,
10304                                  asm, ".4h", ".4h",
10305      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
10306    bits<4> imm;
10307    let Inst{19-16} = imm;
10308  }
10309
10310  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10311                                  V128, V128, vecshiftR16,
10312                                  asm, ".8h", ".8h",
10313      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
10314    bits<4> imm;
10315    let Inst{19-16} = imm;
10316  }
10317  } // Predicates = [HasNEON, HasFullFP16]
10318  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10319                                  V64, V64, vecshiftR32,
10320                                  asm, ".2s", ".2s",
10321      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
10322    bits<5> imm;
10323    let Inst{20-16} = imm;
10324  }
10325
10326  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10327                                  V128, V128, vecshiftR32,
10328                                  asm, ".4s", ".4s",
10329      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
10330    bits<5> imm;
10331    let Inst{20-16} = imm;
10332  }
10333
10334  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10335                                  V128, V128, vecshiftR64,
10336                                  asm, ".2d", ".2d",
10337      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
10338    bits<6> imm;
10339    let Inst{21-16} = imm;
10340  }
10341}
10342
10343multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
10344                                  Intrinsic OpNode> {
10345  let Predicates = [HasNEON, HasFullFP16] in {
10346  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10347                                  V64, V64, vecshiftR16,
10348                                  asm, ".4h", ".4h",
10349      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
10350    bits<4> imm;
10351    let Inst{19-16} = imm;
10352  }
10353
10354  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10355                                  V128, V128, vecshiftR16,
10356                                  asm, ".8h", ".8h",
10357      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
10358    bits<4> imm;
10359    let Inst{19-16} = imm;
10360  }
10361  } // Predicates = [HasNEON, HasFullFP16]
10362
10363  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10364                                  V64, V64, vecshiftR32,
10365                                  asm, ".2s", ".2s",
10366      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
10367    bits<5> imm;
10368    let Inst{20-16} = imm;
10369  }
10370
10371  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10372                                  V128, V128, vecshiftR32,
10373                                  asm, ".4s", ".4s",
10374      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
10375    bits<5> imm;
10376    let Inst{20-16} = imm;
10377  }
10378
10379  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10380                                  V128, V128, vecshiftR64,
10381                                  asm, ".2d", ".2d",
10382      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
10383    bits<6> imm;
10384    let Inst{21-16} = imm;
10385  }
10386}
10387
10388multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
10389                                     SDPatternOperator OpNode> {
10390  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10391                                  V64, V128, vecshiftR16Narrow,
10392                                  asm, ".8b", ".8h",
10393      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
10394    bits<3> imm;
10395    let Inst{18-16} = imm;
10396  }
10397
10398  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10399                                  V128, V128, vecshiftR16Narrow,
10400                                  asm#"2", ".16b", ".8h", []> {
10401    bits<3> imm;
10402    let Inst{18-16} = imm;
10403    let hasSideEffects = 0;
10404  }
10405
10406  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10407                                  V64, V128, vecshiftR32Narrow,
10408                                  asm, ".4h", ".4s",
10409      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
10410    bits<4> imm;
10411    let Inst{19-16} = imm;
10412  }
10413
10414  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10415                                  V128, V128, vecshiftR32Narrow,
10416                                  asm#"2", ".8h", ".4s", []> {
10417    bits<4> imm;
10418    let Inst{19-16} = imm;
10419    let hasSideEffects = 0;
10420  }
10421
10422  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10423                                  V64, V128, vecshiftR64Narrow,
10424                                  asm, ".2s", ".2d",
10425      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
10426    bits<5> imm;
10427    let Inst{20-16} = imm;
10428  }
10429
10430  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10431                                  V128, V128, vecshiftR64Narrow,
10432                                  asm#"2", ".4s", ".2d", []> {
10433    bits<5> imm;
10434    let Inst{20-16} = imm;
10435    let hasSideEffects = 0;
10436  }
10437
10438  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
10439  // themselves, so put them here instead.
10440
10441  // Patterns involving what's effectively an insert high and a normal
10442  // intrinsic, represented by CONCAT_VECTORS.
10443  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
10444                                                   vecshiftR16Narrow:$imm)),
10445            (!cast<Instruction>(NAME # "v16i8_shift")
10446                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10447                V128:$Rn, vecshiftR16Narrow:$imm)>;
10448  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
10449                                                     vecshiftR32Narrow:$imm)),
10450            (!cast<Instruction>(NAME # "v8i16_shift")
10451                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10452                V128:$Rn, vecshiftR32Narrow:$imm)>;
10453  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
10454                                                     vecshiftR64Narrow:$imm)),
10455            (!cast<Instruction>(NAME # "v4i32_shift")
10456                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10457                V128:$Rn, vecshiftR64Narrow:$imm)>;
10458}
10459
10460multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
10461                                SDPatternOperator OpNode> {
10462  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10463                                  V64, V64, vecshiftL8,
10464                                  asm, ".8b", ".8b",
10465                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10466                       (i32 vecshiftL8:$imm)))]> {
10467    bits<3> imm;
10468    let Inst{18-16} = imm;
10469  }
10470
10471  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10472                                  V128, V128, vecshiftL8,
10473                                  asm, ".16b", ".16b",
10474             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10475                   (i32 vecshiftL8:$imm)))]> {
10476    bits<3> imm;
10477    let Inst{18-16} = imm;
10478  }
10479
10480  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10481                                  V64, V64, vecshiftL16,
10482                                  asm, ".4h", ".4h",
10483              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10484                    (i32 vecshiftL16:$imm)))]> {
10485    bits<4> imm;
10486    let Inst{19-16} = imm;
10487  }
10488
10489  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10490                                  V128, V128, vecshiftL16,
10491                                  asm, ".8h", ".8h",
10492            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10493                  (i32 vecshiftL16:$imm)))]> {
10494    bits<4> imm;
10495    let Inst{19-16} = imm;
10496  }
10497
10498  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10499                                  V64, V64, vecshiftL32,
10500                                  asm, ".2s", ".2s",
10501              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10502                    (i32 vecshiftL32:$imm)))]> {
10503    bits<5> imm;
10504    let Inst{20-16} = imm;
10505  }
10506
10507  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10508                                  V128, V128, vecshiftL32,
10509                                  asm, ".4s", ".4s",
10510            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10511                  (i32 vecshiftL32:$imm)))]> {
10512    bits<5> imm;
10513    let Inst{20-16} = imm;
10514  }
10515
10516  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10517                                  V128, V128, vecshiftL64,
10518                                  asm, ".2d", ".2d",
10519            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10520                  (i32 vecshiftL64:$imm)))]> {
10521    bits<6> imm;
10522    let Inst{21-16} = imm;
10523  }
10524}
10525
10526multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
10527                                SDPatternOperator OpNode> {
10528  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10529                                  V64, V64, vecshiftR8,
10530                                  asm, ".8b", ".8b",
10531                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10532                       (i32 vecshiftR8:$imm)))]> {
10533    bits<3> imm;
10534    let Inst{18-16} = imm;
10535  }
10536
10537  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10538                                  V128, V128, vecshiftR8,
10539                                  asm, ".16b", ".16b",
10540             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10541                   (i32 vecshiftR8:$imm)))]> {
10542    bits<3> imm;
10543    let Inst{18-16} = imm;
10544  }
10545
10546  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10547                                  V64, V64, vecshiftR16,
10548                                  asm, ".4h", ".4h",
10549              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10550                    (i32 vecshiftR16:$imm)))]> {
10551    bits<4> imm;
10552    let Inst{19-16} = imm;
10553  }
10554
10555  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10556                                  V128, V128, vecshiftR16,
10557                                  asm, ".8h", ".8h",
10558            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10559                  (i32 vecshiftR16:$imm)))]> {
10560    bits<4> imm;
10561    let Inst{19-16} = imm;
10562  }
10563
10564  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10565                                  V64, V64, vecshiftR32,
10566                                  asm, ".2s", ".2s",
10567              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10568                    (i32 vecshiftR32:$imm)))]> {
10569    bits<5> imm;
10570    let Inst{20-16} = imm;
10571  }
10572
10573  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10574                                  V128, V128, vecshiftR32,
10575                                  asm, ".4s", ".4s",
10576            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10577                  (i32 vecshiftR32:$imm)))]> {
10578    bits<5> imm;
10579    let Inst{20-16} = imm;
10580  }
10581
10582  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10583                                  V128, V128, vecshiftR64,
10584                                  asm, ".2d", ".2d",
10585            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10586                  (i32 vecshiftR64:$imm)))]> {
10587    bits<6> imm;
10588    let Inst{21-16} = imm;
10589  }
10590}
10591
10592let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10593multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
10594                                    SDPatternOperator OpNode = null_frag> {
10595  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10596                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
10597                 [(set (v8i8 V64:$dst),
10598                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10599                           (i32 vecshiftR8:$imm)))]> {
10600    bits<3> imm;
10601    let Inst{18-16} = imm;
10602  }
10603
10604  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10605                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
10606             [(set (v16i8 V128:$dst),
10607               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10608                       (i32 vecshiftR8:$imm)))]> {
10609    bits<3> imm;
10610    let Inst{18-16} = imm;
10611  }
10612
10613  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10614                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
10615              [(set (v4i16 V64:$dst),
10616                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10617                        (i32 vecshiftR16:$imm)))]> {
10618    bits<4> imm;
10619    let Inst{19-16} = imm;
10620  }
10621
10622  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10623                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
10624            [(set (v8i16 V128:$dst),
10625              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10626                      (i32 vecshiftR16:$imm)))]> {
10627    bits<4> imm;
10628    let Inst{19-16} = imm;
10629  }
10630
10631  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10632                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
10633              [(set (v2i32 V64:$dst),
10634                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10635                        (i32 vecshiftR32:$imm)))]> {
10636    bits<5> imm;
10637    let Inst{20-16} = imm;
10638  }
10639
10640  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10641                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
10642            [(set (v4i32 V128:$dst),
10643              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10644                      (i32 vecshiftR32:$imm)))]> {
10645    bits<5> imm;
10646    let Inst{20-16} = imm;
10647  }
10648
10649  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10650                                  V128, V128, vecshiftR64,
10651                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
10652              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10653                      (i32 vecshiftR64:$imm)))]> {
10654    bits<6> imm;
10655    let Inst{21-16} = imm;
10656  }
10657}
10658
10659multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
10660                                    SDPatternOperator OpNode = null_frag> {
10661  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10662                                  V64, V64, vecshiftL8,
10663                                  asm, ".8b", ".8b",
10664                    [(set (v8i8 V64:$dst),
10665                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10666                                  (i32 vecshiftL8:$imm)))]> {
10667    bits<3> imm;
10668    let Inst{18-16} = imm;
10669  }
10670
10671  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10672                                  V128, V128, vecshiftL8,
10673                                  asm, ".16b", ".16b",
10674                    [(set (v16i8 V128:$dst),
10675                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10676                                  (i32 vecshiftL8:$imm)))]> {
10677    bits<3> imm;
10678    let Inst{18-16} = imm;
10679  }
10680
10681  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10682                                  V64, V64, vecshiftL16,
10683                                  asm, ".4h", ".4h",
10684                    [(set (v4i16 V64:$dst),
10685                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10686                                   (i32 vecshiftL16:$imm)))]> {
10687    bits<4> imm;
10688    let Inst{19-16} = imm;
10689  }
10690
10691  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10692                                  V128, V128, vecshiftL16,
10693                                  asm, ".8h", ".8h",
10694                    [(set (v8i16 V128:$dst),
10695                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10696                                  (i32 vecshiftL16:$imm)))]> {
10697    bits<4> imm;
10698    let Inst{19-16} = imm;
10699  }
10700
10701  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10702                                  V64, V64, vecshiftL32,
10703                                  asm, ".2s", ".2s",
10704                    [(set (v2i32 V64:$dst),
10705                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10706                                  (i32 vecshiftL32:$imm)))]> {
10707    bits<5> imm;
10708    let Inst{20-16} = imm;
10709  }
10710
10711  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10712                                  V128, V128, vecshiftL32,
10713                                  asm, ".4s", ".4s",
10714                    [(set (v4i32 V128:$dst),
10715                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10716                                  (i32 vecshiftL32:$imm)))]> {
10717    bits<5> imm;
10718    let Inst{20-16} = imm;
10719  }
10720
10721  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10722                                  V128, V128, vecshiftL64,
10723                                  asm, ".2d", ".2d",
10724                    [(set (v2i64 V128:$dst),
10725                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10726                                  (i32 vecshiftL64:$imm)))]> {
10727    bits<6> imm;
10728    let Inst{21-16} = imm;
10729  }
10730}
10731
10732multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
10733                                   SDPatternOperator OpNode> {
10734  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10735                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
10736      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
10737    bits<3> imm;
10738    let Inst{18-16} = imm;
10739  }
10740
10741  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10742                                  V128, V128, vecshiftL8,
10743                                  asm#"2", ".8h", ".16b",
10744      [(set (v8i16 V128:$Rd),
10745            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
10746    bits<3> imm;
10747    let Inst{18-16} = imm;
10748  }
10749
10750  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10751                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
10752      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
10753    bits<4> imm;
10754    let Inst{19-16} = imm;
10755  }
10756
10757  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10758                                  V128, V128, vecshiftL16,
10759                                  asm#"2", ".4s", ".8h",
10760      [(set (v4i32 V128:$Rd),
10761            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
10762
10763    bits<4> imm;
10764    let Inst{19-16} = imm;
10765  }
10766
10767  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10768                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
10769      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
10770    bits<5> imm;
10771    let Inst{20-16} = imm;
10772  }
10773
10774  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10775                                  V128, V128, vecshiftL32,
10776                                  asm#"2", ".2d", ".4s",
10777      [(set (v2i64 V128:$Rd),
10778            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
10779    bits<5> imm;
10780    let Inst{20-16} = imm;
10781  }
10782}
10783
10784
10785//---
10786// Vector load/store
10787//---
10788// SIMD ldX/stX no-index memory references don't allow the optional
10789// ", #0" constant and handle post-indexing explicitly, so we use
10790// a more specialized parse method for them. Otherwise, it's the same as
10791// the general GPR64sp handling.
10792
10793class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
10794                   string asm, dag oops, dag iops, list<dag> pattern>
10795  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
10796  bits<5> Vt;
10797  bits<5> Rn;
10798  let Inst{31} = 0;
10799  let Inst{30} = Q;
10800  let Inst{29-23} = 0b0011000;
10801  let Inst{22} = L;
10802  let Inst{21-16} = 0b000000;
10803  let Inst{15-12} = opcode;
10804  let Inst{11-10} = size;
10805  let Inst{9-5} = Rn;
10806  let Inst{4-0} = Vt;
10807}
10808
10809class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
10810                       string asm, dag oops, dag iops>
10811  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
10812  bits<5> Vt;
10813  bits<5> Rn;
10814  bits<5> Xm;
10815  let Inst{31} = 0;
10816  let Inst{30} = Q;
10817  let Inst{29-23} = 0b0011001;
10818  let Inst{22} = L;
10819  let Inst{21} = 0;
10820  let Inst{20-16} = Xm;
10821  let Inst{15-12} = opcode;
10822  let Inst{11-10} = size;
10823  let Inst{9-5} = Rn;
10824  let Inst{4-0} = Vt;
10825}
10826
10827// The immediate form of AdvSIMD post-indexed addressing is encoded with
10828// register post-index addressing from the zero register.
10829multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
10830                           int Offset, int Size> {
10831  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
10832  //      "ld1\t$Vt, [$Rn], #16"
10833  // may get mapped to
10834  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
10835  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10836                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10837                      GPR64sp:$Rn,
10838                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10839                      XZR), 1>;
10840
10841  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
10842  //      "ld1.8b\t$Vt, [$Rn], #16"
10843  // may get mapped to
10844  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
10845  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10846                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10847                      GPR64sp:$Rn,
10848                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10849                      XZR), 0>;
10850
10851  // E.g. "ld1.8b { v0, v1 }, [x1]"
10852  //      "ld1\t$Vt, [$Rn]"
10853  // may get mapped to
10854  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10855  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10856                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10857                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10858                      GPR64sp:$Rn), 0>;
10859
10860  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10861  //      "ld1\t$Vt, [$Rn], $Xm"
10862  // may get mapped to
10863  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10864  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10865                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10866                      GPR64sp:$Rn,
10867                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10868                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10869}
10870
10871multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10872                       int Offset128, int Offset64, bits<4> opcode> {
10873  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10874    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10875                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10876                           (ins GPR64sp:$Rn), []>;
10877    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10878                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10879                           (ins GPR64sp:$Rn), []>;
10880    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10881                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10882                           (ins GPR64sp:$Rn), []>;
10883    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10884                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10885                           (ins GPR64sp:$Rn), []>;
10886    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10887                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10888                           (ins GPR64sp:$Rn), []>;
10889    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10890                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10891                           (ins GPR64sp:$Rn), []>;
10892    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10893                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10894                           (ins GPR64sp:$Rn), []>;
10895
10896
10897    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10898                       (outs GPR64sp:$wback,
10899                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10900                       (ins GPR64sp:$Rn,
10901                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10902    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10903                       (outs GPR64sp:$wback,
10904                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10905                       (ins GPR64sp:$Rn,
10906                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10907    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10908                       (outs GPR64sp:$wback,
10909                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10910                       (ins GPR64sp:$Rn,
10911                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10912    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10913                       (outs GPR64sp:$wback,
10914                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10915                       (ins GPR64sp:$Rn,
10916                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10917    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10918                       (outs GPR64sp:$wback,
10919                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10920                       (ins GPR64sp:$Rn,
10921                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10922    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10923                       (outs GPR64sp:$wback,
10924                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10925                       (ins GPR64sp:$Rn,
10926                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10927    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10928                       (outs GPR64sp:$wback,
10929                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10930                       (ins GPR64sp:$Rn,
10931                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10932  }
10933
10934  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10935  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10936  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10937  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10938  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10939  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10940  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10941}
10942
10943// Only ld1/st1 has a v1d version.
10944multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10945                       int Offset128, int Offset64, bits<4> opcode> {
10946  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10947    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10948                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10949                                 GPR64sp:$Rn), []>;
10950    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10951                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10952                                GPR64sp:$Rn), []>;
10953    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10954                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10955                                GPR64sp:$Rn), []>;
10956    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10957                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10958                                GPR64sp:$Rn), []>;
10959    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10960                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10961                                GPR64sp:$Rn), []>;
10962    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10963                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10964                                GPR64sp:$Rn), []>;
10965    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10966                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10967                                GPR64sp:$Rn), []>;
10968
10969    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10970                       (outs GPR64sp:$wback),
10971                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10972                            GPR64sp:$Rn,
10973                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10974    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10975                       (outs GPR64sp:$wback),
10976                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10977                            GPR64sp:$Rn,
10978                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10979    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10980                       (outs GPR64sp:$wback),
10981                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10982                            GPR64sp:$Rn,
10983                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10984    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10985                       (outs GPR64sp:$wback),
10986                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10987                            GPR64sp:$Rn,
10988                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10989    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10990                       (outs GPR64sp:$wback),
10991                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10992                            GPR64sp:$Rn,
10993                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10994    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10995                       (outs GPR64sp:$wback),
10996                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10997                            GPR64sp:$Rn,
10998                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10999    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
11000                       (outs GPR64sp:$wback),
11001                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
11002                            GPR64sp:$Rn,
11003                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
11004  }
11005
11006  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
11007  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
11008  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
11009  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
11010  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
11011  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
11012  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
11013}
11014
11015multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
11016                       int Offset128, int Offset64, bits<4> opcode>
11017  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
11018
11019  // LD1 instructions have extra "1d" variants.
11020  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
11021    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
11022                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
11023                           (ins GPR64sp:$Rn), []>;
11024
11025    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
11026                       (outs GPR64sp:$wback,
11027                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
11028                       (ins GPR64sp:$Rn,
11029                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
11030  }
11031
11032  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
11033}
11034
11035multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
11036                       int Offset128, int Offset64, bits<4> opcode>
11037  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
11038
11039  // ST1 instructions have extra "1d" variants.
11040  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
11041    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
11042                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
11043                                GPR64sp:$Rn), []>;
11044
11045    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
11046                       (outs GPR64sp:$wback),
11047                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
11048                            GPR64sp:$Rn,
11049                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
11050  }
11051
11052  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
11053}
11054
11055multiclass SIMDLd1Multiple<string asm> {
11056  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
11057  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
11058  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
11059  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
11060}
11061
11062multiclass SIMDSt1Multiple<string asm> {
11063  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
11064  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
11065  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
11066  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
11067}
11068
11069multiclass SIMDLd2Multiple<string asm> {
11070  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
11071}
11072
11073multiclass SIMDSt2Multiple<string asm> {
11074  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
11075}
11076
11077multiclass SIMDLd3Multiple<string asm> {
11078  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
11079}
11080
11081multiclass SIMDSt3Multiple<string asm> {
11082  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
11083}
11084
11085multiclass SIMDLd4Multiple<string asm> {
11086  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
11087}
11088
11089multiclass SIMDSt4Multiple<string asm> {
11090  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
11091}
11092
11093//---
11094// AdvSIMD Load/store single-element
11095//---
11096
11097class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
11098                         string asm, string operands, string cst,
11099                         dag oops, dag iops, list<dag> pattern>
11100  : I<oops, iops, asm, operands, cst, pattern> {
11101  bits<5> Vt;
11102  bits<5> Rn;
11103  let Inst{31} = 0;
11104  let Inst{29-24} = 0b001101;
11105  let Inst{22} = L;
11106  let Inst{21} = R;
11107  let Inst{15-13} = opcode;
11108  let Inst{9-5} = Rn;
11109  let Inst{4-0} = Vt;
11110}
11111
11112class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
11113                         string asm, string operands, string cst,
11114                         dag oops, dag iops, list<dag> pattern>
11115  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
11116  bits<5> Vt;
11117  bits<5> Rn;
11118  let Inst{31} = 0;
11119  let Inst{29-24} = 0b001101;
11120  let Inst{22} = L;
11121  let Inst{21} = R;
11122  let Inst{15-13} = opcode;
11123  let Inst{9-5} = Rn;
11124  let Inst{4-0} = Vt;
11125}
11126
11127
11128let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11129class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
11130                  DAGOperand listtype>
11131  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
11132                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
11133                       []> {
11134  let Inst{30} = Q;
11135  let Inst{23} = 0;
11136  let Inst{20-16} = 0b00000;
11137  let Inst{12} = S;
11138  let Inst{11-10} = size;
11139}
11140let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11141class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
11142                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
11143  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
11144                       "$Rn = $wback",
11145                       (outs GPR64sp:$wback, listtype:$Vt),
11146                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
11147  bits<5> Xm;
11148  let Inst{30} = Q;
11149  let Inst{23} = 1;
11150  let Inst{20-16} = Xm;
11151  let Inst{12} = S;
11152  let Inst{11-10} = size;
11153}
11154
11155multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
11156                          int Offset, int Size> {
11157  // E.g. "ld1r { v0.8b }, [x1], #1"
11158  //      "ld1r.8b\t$Vt, [$Rn], #1"
11159  // may get mapped to
11160  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
11161  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
11162                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
11163                      GPR64sp:$Rn,
11164                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
11165                      XZR), 1>;
11166
11167  // E.g. "ld1r.8b { v0 }, [x1], #1"
11168  //      "ld1r.8b\t$Vt, [$Rn], #1"
11169  // may get mapped to
11170  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
11171  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
11172                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
11173                      GPR64sp:$Rn,
11174                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
11175                      XZR), 0>;
11176
11177  // E.g. "ld1r.8b { v0 }, [x1]"
11178  //      "ld1r.8b\t$Vt, [$Rn]"
11179  // may get mapped to
11180  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
11181  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
11182                  (!cast<Instruction>(BaseName # "v" # layout)
11183                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
11184                      GPR64sp:$Rn), 0>;
11185
11186  // E.g. "ld1r.8b { v0 }, [x1], x2"
11187  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
11188  // may get mapped to
11189  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
11190  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
11191                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
11192                      GPR64sp:$Rn,
11193                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
11194                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
11195}
11196
11197multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
11198  int Offset1, int Offset2, int Offset4, int Offset8> {
11199  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
11200                        !cast<DAGOperand>("VecList" # Count # "8b")>;
11201  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
11202                        !cast<DAGOperand>("VecList" # Count #"16b")>;
11203  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
11204                        !cast<DAGOperand>("VecList" # Count #"4h")>;
11205  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
11206                        !cast<DAGOperand>("VecList" # Count #"8h")>;
11207  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
11208                        !cast<DAGOperand>("VecList" # Count #"2s")>;
11209  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
11210                        !cast<DAGOperand>("VecList" # Count #"4s")>;
11211  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
11212                        !cast<DAGOperand>("VecList" # Count #"1d")>;
11213  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
11214                        !cast<DAGOperand>("VecList" # Count #"2d")>;
11215
11216  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
11217                                 !cast<DAGOperand>("VecList" # Count # "8b"),
11218                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
11219  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
11220                                 !cast<DAGOperand>("VecList" # Count # "16b"),
11221                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
11222  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
11223                                 !cast<DAGOperand>("VecList" # Count # "4h"),
11224                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
11225  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
11226                                 !cast<DAGOperand>("VecList" # Count # "8h"),
11227                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
11228  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
11229                                 !cast<DAGOperand>("VecList" # Count # "2s"),
11230                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
11231  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
11232                                 !cast<DAGOperand>("VecList" # Count # "4s"),
11233                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
11234  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
11235                                 !cast<DAGOperand>("VecList" # Count # "1d"),
11236                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
11237  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
11238                                 !cast<DAGOperand>("VecList" # Count # "2d"),
11239                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
11240
11241  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
11242  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
11243  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
11244  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
11245  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
11246  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
11247  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
11248  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
11249}
11250
11251class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
11252                      dag oops, dag iops, list<dag> pattern>
11253  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
11254                       pattern> {
11255  // idx encoded in Q:S:size fields.
11256  bits<4> idx;
11257  let Inst{30} = idx{3};
11258  let Inst{23} = 0;
11259  let Inst{20-16} = 0b00000;
11260  let Inst{12} = idx{2};
11261  let Inst{11-10} = idx{1-0};
11262}
11263class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
11264                      dag oops, dag iops, list<dag> pattern>
11265  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
11266                           oops, iops, pattern> {
11267  // idx encoded in Q:S:size fields.
11268  bits<4> idx;
11269  let Inst{30} = idx{3};
11270  let Inst{23} = 0;
11271  let Inst{20-16} = 0b00000;
11272  let Inst{12} = idx{2};
11273  let Inst{11-10} = idx{1-0};
11274}
11275class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
11276                          dag oops, dag iops>
11277  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11278                       "$Rn = $wback", oops, iops, []> {
11279  // idx encoded in Q:S:size fields.
11280  bits<4> idx;
11281  bits<5> Xm;
11282  let Inst{30} = idx{3};
11283  let Inst{23} = 1;
11284  let Inst{20-16} = Xm;
11285  let Inst{12} = idx{2};
11286  let Inst{11-10} = idx{1-0};
11287}
11288class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
11289                          dag oops, dag iops>
11290  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11291                           "$Rn = $wback", oops, iops, []> {
11292  // idx encoded in Q:S:size fields.
11293  bits<4> idx;
11294  bits<5> Xm;
11295  let Inst{30} = idx{3};
11296  let Inst{23} = 1;
11297  let Inst{20-16} = Xm;
11298  let Inst{12} = idx{2};
11299  let Inst{11-10} = idx{1-0};
11300}
11301
11302class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
11303                      dag oops, dag iops, list<dag> pattern>
11304  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
11305                       pattern> {
11306  // idx encoded in Q:S:size<1> fields.
11307  bits<3> idx;
11308  let Inst{30} = idx{2};
11309  let Inst{23} = 0;
11310  let Inst{20-16} = 0b00000;
11311  let Inst{12} = idx{1};
11312  let Inst{11} = idx{0};
11313  let Inst{10} = size;
11314}
11315class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
11316                      dag oops, dag iops, list<dag> pattern>
11317  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
11318                           oops, iops, pattern> {
11319  // idx encoded in Q:S:size<1> fields.
11320  bits<3> idx;
11321  let Inst{30} = idx{2};
11322  let Inst{23} = 0;
11323  let Inst{20-16} = 0b00000;
11324  let Inst{12} = idx{1};
11325  let Inst{11} = idx{0};
11326  let Inst{10} = size;
11327}
11328
11329class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
11330                          dag oops, dag iops>
11331  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11332                       "$Rn = $wback", oops, iops, []> {
11333  // idx encoded in Q:S:size<1> fields.
11334  bits<3> idx;
11335  bits<5> Xm;
11336  let Inst{30} = idx{2};
11337  let Inst{23} = 1;
11338  let Inst{20-16} = Xm;
11339  let Inst{12} = idx{1};
11340  let Inst{11} = idx{0};
11341  let Inst{10} = size;
11342}
11343class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
11344                          dag oops, dag iops>
11345  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11346                           "$Rn = $wback", oops, iops, []> {
11347  // idx encoded in Q:S:size<1> fields.
11348  bits<3> idx;
11349  bits<5> Xm;
11350  let Inst{30} = idx{2};
11351  let Inst{23} = 1;
11352  let Inst{20-16} = Xm;
11353  let Inst{12} = idx{1};
11354  let Inst{11} = idx{0};
11355  let Inst{10} = size;
11356}
11357class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
11358                      dag oops, dag iops, list<dag> pattern>
11359  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
11360                       pattern> {
11361  // idx encoded in Q:S fields.
11362  bits<2> idx;
11363  let Inst{30} = idx{1};
11364  let Inst{23} = 0;
11365  let Inst{20-16} = 0b00000;
11366  let Inst{12} = idx{0};
11367  let Inst{11-10} = size;
11368}
11369class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
11370                      dag oops, dag iops, list<dag> pattern>
11371  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
11372                           oops, iops, pattern> {
11373  // idx encoded in Q:S fields.
11374  bits<2> idx;
11375  let Inst{30} = idx{1};
11376  let Inst{23} = 0;
11377  let Inst{20-16} = 0b00000;
11378  let Inst{12} = idx{0};
11379  let Inst{11-10} = size;
11380}
11381class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
11382                          string asm, dag oops, dag iops>
11383  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11384                       "$Rn = $wback", oops, iops, []> {
11385  // idx encoded in Q:S fields.
11386  bits<2> idx;
11387  bits<5> Xm;
11388  let Inst{30} = idx{1};
11389  let Inst{23} = 1;
11390  let Inst{20-16} = Xm;
11391  let Inst{12} = idx{0};
11392  let Inst{11-10} = size;
11393}
11394class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
11395                          string asm, dag oops, dag iops>
11396  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11397                           "$Rn = $wback", oops, iops, []> {
11398  // idx encoded in Q:S fields.
11399  bits<2> idx;
11400  bits<5> Xm;
11401  let Inst{30} = idx{1};
11402  let Inst{23} = 1;
11403  let Inst{20-16} = Xm;
11404  let Inst{12} = idx{0};
11405  let Inst{11-10} = size;
11406}
11407class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
11408                      dag oops, dag iops, list<dag> pattern>
11409  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
11410                       pattern> {
11411  // idx encoded in Q field.
11412  bits<1> idx;
11413  let Inst{30} = idx;
11414  let Inst{23} = 0;
11415  let Inst{20-16} = 0b00000;
11416  let Inst{12} = 0;
11417  let Inst{11-10} = size;
11418}
11419class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
11420                      dag oops, dag iops, list<dag> pattern>
11421  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
11422                           oops, iops, pattern> {
11423  // idx encoded in Q field.
11424  bits<1> idx;
11425  let Inst{30} = idx;
11426  let Inst{23} = 0;
11427  let Inst{20-16} = 0b00000;
11428  let Inst{12} = 0;
11429  let Inst{11-10} = size;
11430}
11431class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
11432                          string asm, dag oops, dag iops>
11433  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11434                       "$Rn = $wback", oops, iops, []> {
11435  // idx encoded in Q field.
11436  bits<1> idx;
11437  bits<5> Xm;
11438  let Inst{30} = idx;
11439  let Inst{23} = 1;
11440  let Inst{20-16} = Xm;
11441  let Inst{12} = 0;
11442  let Inst{11-10} = size;
11443}
11444class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
11445                          string asm, dag oops, dag iops>
11446  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11447                           "$Rn = $wback", oops, iops, []> {
11448  // idx encoded in Q field.
11449  bits<1> idx;
11450  bits<5> Xm;
11451  let Inst{30} = idx;
11452  let Inst{23} = 1;
11453  let Inst{20-16} = Xm;
11454  let Inst{12} = 0;
11455  let Inst{11-10} = size;
11456}
11457
11458let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11459multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
11460                         RegisterOperand listtype,
11461                         RegisterOperand GPR64pi> {
11462  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
11463                           (outs listtype:$dst),
11464                           (ins listtype:$Vt, VectorIndexB:$idx,
11465                                GPR64sp:$Rn), []>;
11466
11467  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
11468                            (outs GPR64sp:$wback, listtype:$dst),
11469                            (ins listtype:$Vt, VectorIndexB:$idx,
11470                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11471}
11472let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11473multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
11474                         RegisterOperand listtype,
11475                         RegisterOperand GPR64pi> {
11476  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
11477                            (outs listtype:$dst),
11478                            (ins listtype:$Vt, VectorIndexH:$idx,
11479                                 GPR64sp:$Rn), []>;
11480
11481  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
11482                            (outs GPR64sp:$wback, listtype:$dst),
11483                            (ins listtype:$Vt, VectorIndexH:$idx,
11484                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11485}
11486let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11487multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
11488                         RegisterOperand listtype,
11489                         RegisterOperand GPR64pi> {
11490  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
11491                            (outs listtype:$dst),
11492                            (ins listtype:$Vt, VectorIndexS:$idx,
11493                                 GPR64sp:$Rn), []>;
11494
11495  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
11496                            (outs GPR64sp:$wback, listtype:$dst),
11497                            (ins listtype:$Vt, VectorIndexS:$idx,
11498                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11499}
11500let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11501multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
11502                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11503  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
11504                            (outs listtype:$dst),
11505                            (ins listtype:$Vt, VectorIndexD:$idx,
11506                                 GPR64sp:$Rn), []>;
11507
11508  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
11509                            (outs GPR64sp:$wback, listtype:$dst),
11510                            (ins listtype:$Vt, VectorIndexD:$idx,
11511                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11512}
11513let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11514multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
11515                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11516  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
11517                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
11518                                        GPR64sp:$Rn), []>;
11519
11520  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
11521                                    (outs GPR64sp:$wback),
11522                                    (ins listtype:$Vt, VectorIndexB:$idx,
11523                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
11524}
11525let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11526multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
11527                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11528  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
11529                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
11530                                         GPR64sp:$Rn), []>;
11531
11532  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
11533                            (outs GPR64sp:$wback),
11534                            (ins listtype:$Vt, VectorIndexH:$idx,
11535                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11536}
11537let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11538multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
11539                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11540  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
11541                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
11542                                         GPR64sp:$Rn), []>;
11543
11544  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
11545                            (outs GPR64sp:$wback),
11546                            (ins listtype:$Vt, VectorIndexS:$idx,
11547                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11548}
11549let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11550multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
11551                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11552  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
11553                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
11554                                         GPR64sp:$Rn), []>;
11555
11556  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
11557                            (outs GPR64sp:$wback),
11558                            (ins listtype:$Vt, VectorIndexD:$idx,
11559                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11560}
11561
11562multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
11563                                 string Count, int Offset, Operand idxtype> {
11564  // E.g. "ld1 { v0.8b }[0], [x1], #1"
11565  //      "ld1\t$Vt, [$Rn], #1"
11566  // may get mapped to
11567  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
11568  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
11569                  (!cast<Instruction>(NAME # Type  # "_POST")
11570                      GPR64sp:$Rn,
11571                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
11572                      idxtype:$idx, XZR), 1>;
11573
11574  // E.g. "ld1.8b { v0 }[0], [x1], #1"
11575  //      "ld1.8b\t$Vt, [$Rn], #1"
11576  // may get mapped to
11577  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
11578  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
11579                  (!cast<Instruction>(NAME # Type # "_POST")
11580                      GPR64sp:$Rn,
11581                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11582                      idxtype:$idx, XZR), 0>;
11583
11584  // E.g. "ld1.8b { v0 }[0], [x1]"
11585  //      "ld1.8b\t$Vt, [$Rn]"
11586  // may get mapped to
11587  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
11588  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
11589                      (!cast<Instruction>(NAME # Type)
11590                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11591                         idxtype:$idx, GPR64sp:$Rn), 0>;
11592
11593  // E.g. "ld1.8b { v0 }[0], [x1], x2"
11594  //      "ld1.8b\t$Vt, [$Rn], $Xm"
11595  // may get mapped to
11596  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
11597  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
11598                      (!cast<Instruction>(NAME # Type # "_POST")
11599                         GPR64sp:$Rn,
11600                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11601                         idxtype:$idx,
11602                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
11603}
11604
11605multiclass SIMDLdSt1SingleAliases<string asm> {
11606  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
11607  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
11608  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
11609  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
11610}
11611
11612multiclass SIMDLdSt2SingleAliases<string asm> {
11613  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
11614  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
11615  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
11616  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
11617}
11618
11619multiclass SIMDLdSt3SingleAliases<string asm> {
11620  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
11621  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
11622  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
11623  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
11624}
11625
11626multiclass SIMDLdSt4SingleAliases<string asm> {
11627  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
11628  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
11629  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
11630  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
11631}
11632} // end of 'let Predicates = [HasNEON]'
11633
11634//----------------------------------------------------------------------------
11635// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
11636//----------------------------------------------------------------------------
11637
11638let Predicates = [HasNEON, HasRDM] in {
11639
11640class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
11641                                    RegisterOperand regtype, string asm,
11642                                    string kind, list<dag> pattern>
11643  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
11644                                pattern> {
11645}
11646multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
11647                                             SDPatternOperator op> {
11648  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
11649    [(set (v4i16 V64:$dst),
11650          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
11651  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
11652    [(set (v8i16 V128:$dst),
11653          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
11654  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
11655    [(set (v2i32 V64:$dst),
11656          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
11657  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
11658    [(set (v4i32 V128:$dst),
11659          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
11660}
11661
11662multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
11663                                     SDPatternOperator op> {
11664  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
11665                                          V64, V64, V128_lo, VectorIndexH,
11666                                          asm, ".4h", ".4h", ".4h", ".h",
11667    [(set (v4i16 V64:$dst),
11668          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
11669                     (dup_v8i16 (v8i16 V128_lo:$Rm),
11670                                 VectorIndexH:$idx))))]> {
11671    bits<3> idx;
11672    let Inst{11} = idx{2};
11673    let Inst{21} = idx{1};
11674    let Inst{20} = idx{0};
11675  }
11676
11677  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
11678                                          V128, V128, V128_lo, VectorIndexH,
11679                                          asm, ".8h", ".8h", ".8h", ".h",
11680    [(set (v8i16 V128:$dst),
11681          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
11682                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
11683                                              VectorIndexH:$idx)))))]> {
11684    bits<3> idx;
11685    let Inst{11} = idx{2};
11686    let Inst{21} = idx{1};
11687    let Inst{20} = idx{0};
11688  }
11689
11690  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
11691                                          V64, V64, V128, VectorIndexS,
11692                                          asm, ".2s", ".2s", ".2s", ".s",
11693    [(set (v2i32 V64:$dst),
11694          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
11695                     (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
11696    bits<2> idx;
11697    let Inst{11} = idx{1};
11698    let Inst{21} = idx{0};
11699  }
11700
11701  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
11702                                          V128, V128, V128, VectorIndexS,
11703                                          asm, ".4s", ".4s", ".4s", ".s",
11704    [(set (v4i32 V128:$dst),
11705          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11706                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
11707                                              VectorIndexS:$idx)))))]> {
11708    bits<2> idx;
11709    let Inst{11} = idx{1};
11710    let Inst{21} = idx{0};
11711  }
11712
11713  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
11714                                          FPR16Op, FPR16Op, V128_lo,
11715                                          VectorIndexH, asm, ".h", "", "", ".h",
11716                                          []> {
11717    bits<3> idx;
11718    let Inst{11} = idx{2};
11719    let Inst{21} = idx{1};
11720    let Inst{20} = idx{0};
11721  }
11722
11723  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
11724                                          FPR32Op, FPR32Op, V128, VectorIndexS,
11725                                          asm, ".s", "", "", ".s",
11726    [(set (i32 FPR32Op:$dst),
11727          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
11728                   (i32 (vector_extract (v4i32 V128:$Rm),
11729                                        VectorIndexS:$idx)))))]> {
11730    bits<2> idx;
11731    let Inst{11} = idx{1};
11732    let Inst{21} = idx{0};
11733  }
11734}
11735} // let Predicates = [HasNeon, HasRDM]
11736
11737//----------------------------------------------------------------------------
11738// ARMv8.3 Complex ADD/MLA instructions
11739//----------------------------------------------------------------------------
11740
11741class ComplexRotationOperand<int Angle, int Remainder, string Type>
11742  : AsmOperandClass {
11743  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
11744  let DiagnosticType = "InvalidComplexRotation" # Type;
11745  let Name = "ComplexRotation" # Type;
11746}
11747def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11748                                                  SDNodeXForm<imm, [{
11749  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
11750}]>> {
11751  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
11752  let PrintMethod = "printComplexRotationOp<90, 0>";
11753}
11754def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11755                                                  SDNodeXForm<imm, [{
11756  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
11757}]>> {
11758  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
11759  let PrintMethod = "printComplexRotationOp<180, 90>";
11760}
11761let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11762class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
11763                                     RegisterOperand regtype, Operand rottype,
11764                                     string asm, string kind, list<dag> pattern>
11765  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11766      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11767      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
11768    Sched<[!if(Q, WriteVq, WriteVd)]> {
11769  bits<5> Rd;
11770  bits<5> Rn;
11771  bits<5> Rm;
11772  bits<1> rot;
11773  let Inst{31}    = 0;
11774  let Inst{30}    = Q;
11775  let Inst{29}    = U;
11776  let Inst{28-24} = 0b01110;
11777  let Inst{23-22} = size;
11778  let Inst{21}    = 0;
11779  let Inst{20-16} = Rm;
11780  let Inst{15-13} = opcode;
11781  // Non-tied version (FCADD) only has one rotation bit
11782  let Inst{12}    = rot;
11783  let Inst{11}    = 0;
11784  let Inst{10}    = 1;
11785  let Inst{9-5}   = Rn;
11786  let Inst{4-0}   = Rd;
11787}
11788
11789//8.3 CompNum - Floating-point complex number support
11790multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
11791                                          string asm, SDPatternOperator OpNode>{
11792  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11793  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
11794              asm, ".4h",
11795              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11796                                              (v4f16 V64:$Rn),
11797                                              (v4f16 V64:$Rm),
11798                                              (i32 rottype:$rot)))]>;
11799
11800  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
11801              asm, ".8h",
11802              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11803                                               (v8f16 V128:$Rn),
11804                                               (v8f16 V128:$Rm),
11805                                               (i32 rottype:$rot)))]>;
11806  }
11807
11808  let Predicates = [HasComplxNum, HasNEON] in {
11809  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
11810              asm, ".2s",
11811              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11812                                              (v2f32 V64:$Rn),
11813                                              (v2f32 V64:$Rm),
11814                                              (i32 rottype:$rot)))]>;
11815
11816  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
11817              asm, ".4s",
11818              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11819                                               (v4f32 V128:$Rn),
11820                                               (v4f32 V128:$Rm),
11821                                               (i32 rottype:$rot)))]>;
11822
11823  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
11824              asm, ".2d",
11825              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11826                                               (v2f64 V128:$Rn),
11827                                               (v2f64 V128:$Rm),
11828                                               (i32 rottype:$rot)))]>;
11829  }
11830}
11831
11832let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11833class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
11834                                         bits<3> opcode,
11835                                         RegisterOperand regtype,
11836                                         Operand rottype, string asm,
11837                                         string kind, list<dag> pattern>
11838  : I<(outs regtype:$dst),
11839      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11840      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11841      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
11842    Sched<[!if(Q, WriteVq, WriteVd)]> {
11843  bits<5> Rd;
11844  bits<5> Rn;
11845  bits<5> Rm;
11846  bits<2> rot;
11847  let Inst{31}    = 0;
11848  let Inst{30}    = Q;
11849  let Inst{29}    = U;
11850  let Inst{28-24} = 0b01110;
11851  let Inst{23-22} = size;
11852  let Inst{21}    = 0;
11853  let Inst{20-16} = Rm;
11854  let Inst{15-13} = opcode;
11855  let Inst{12-11} = rot;
11856  let Inst{10}    = 1;
11857  let Inst{9-5}   = Rn;
11858  let Inst{4-0}   = Rd;
11859}
11860
11861multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11862                                             Operand rottype, string asm,
11863                                             SDPatternOperator OpNode> {
11864  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11865  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11866              rottype, asm, ".4h",
11867              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11868                                              (v4f16 V64:$Rn),
11869                                              (v4f16 V64:$Rm),
11870                                              (i32 rottype:$rot)))]>;
11871
11872  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11873              rottype, asm, ".8h",
11874              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11875                                               (v8f16 V128:$Rn),
11876                                               (v8f16 V128:$Rm),
11877                                               (i32 rottype:$rot)))]>;
11878  }
11879
11880  let Predicates = [HasComplxNum, HasNEON] in {
11881  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11882              rottype, asm, ".2s",
11883              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11884                                              (v2f32 V64:$Rn),
11885                                              (v2f32 V64:$Rm),
11886                                              (i32 rottype:$rot)))]>;
11887
11888  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11889              rottype, asm, ".4s",
11890              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11891                                               (v4f32 V128:$Rn),
11892                                               (v4f32 V128:$Rm),
11893                                               (i32 rottype:$rot)))]>;
11894
11895  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11896              rottype, asm, ".2d",
11897              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11898                                               (v2f64 V128:$Rn),
11899                                               (v2f64 V128:$Rm),
11900                                               (i32 rottype:$rot)))]>;
11901  }
11902}
11903
11904let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11905class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11906                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11907                                 RegisterOperand lhs_reg,
11908                                 RegisterOperand rhs_reg, Operand vec_idx,
11909                                 Operand rottype, string asm, string apple_kind,
11910                                 string dst_kind, string lhs_kind,
11911                                 string rhs_kind, list<dag> pattern>
11912  : I<(outs dst_reg:$dst),
11913      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11914      asm,
11915      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11916      "$idx, $rot" # "|" # apple_kind #
11917      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11918    Sched<[!if(Q, WriteVq, WriteVd)]> {
11919  bits<5> Rd;
11920  bits<5> Rn;
11921  bits<5> Rm;
11922  bits<2> rot;
11923
11924  let Inst{31}    = 0;
11925  let Inst{30}    = Q;
11926  let Inst{29}    = U;
11927  let Inst{28}    = Scalar;
11928  let Inst{27-24} = 0b1111;
11929  let Inst{23-22} = size;
11930  // Bit 21 must be set by the derived class.
11931  let Inst{20-16} = Rm;
11932  let Inst{15}    = opc1;
11933  let Inst{14-13} = rot;
11934  let Inst{12}    = opc2;
11935  // Bit 11 must be set by the derived class.
11936  let Inst{10}    = 0;
11937  let Inst{9-5}   = Rn;
11938  let Inst{4-0}   = Rd;
11939}
11940
11941// The complex instructions index by pairs of elements, so the VectorIndexes
11942// don't match the lane types, and the index bits are different to the other
11943// classes.
11944multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11945                                     string asm> {
11946  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11947  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11948                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11949                      ".4h", ".h", []> {
11950    bits<1> idx;
11951    let Inst{11} = 0;
11952    let Inst{21} = idx{0};
11953  }
11954
11955  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11956                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11957                      ".8h", ".8h", ".h", []> {
11958    bits<2> idx;
11959    let Inst{11} = idx{1};
11960    let Inst{21} = idx{0};
11961  }
11962  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11963
11964  let Predicates = [HasComplxNum, HasNEON] in {
11965  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11966                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11967                      ".4s", ".4s", ".s", []> {
11968    bits<1> idx;
11969    let Inst{11} = idx{0};
11970    let Inst{21} = 0;
11971  }
11972  } // Predicates = [HasComplxNum, HasNEON]
11973}
11974
11975//----------------------------------------------------------------------------
11976// Crypto extensions
11977//----------------------------------------------------------------------------
11978
11979let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11980class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11981              list<dag> pat>
11982  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11983    Sched<[WriteVq]>{
11984  bits<5> Rd;
11985  bits<5> Rn;
11986  let Inst{31-16} = 0b0100111000101000;
11987  let Inst{15-12} = opc;
11988  let Inst{11-10} = 0b10;
11989  let Inst{9-5}   = Rn;
11990  let Inst{4-0}   = Rd;
11991}
11992
11993class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11994  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11995            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11996
11997class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11998  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11999            "$Rd = $dst",
12000            [(set (v16i8 V128:$dst),
12001                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
12002
12003let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
12004class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
12005                     dag oops, dag iops, list<dag> pat>
12006  : I<oops, iops, asm,
12007      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
12008      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
12009    Sched<[WriteVq]>{
12010  bits<5> Rd;
12011  bits<5> Rn;
12012  bits<5> Rm;
12013  let Inst{31-21} = 0b01011110000;
12014  let Inst{20-16} = Rm;
12015  let Inst{15}    = 0;
12016  let Inst{14-12} = opc;
12017  let Inst{11-10} = 0b00;
12018  let Inst{9-5}   = Rn;
12019  let Inst{4-0}   = Rd;
12020}
12021
12022class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
12023  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
12024                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
12025                   [(set (v4i32 FPR128:$dst),
12026                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
12027                                 (v4i32 V128:$Rm)))]>;
12028
12029class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
12030  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
12031                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
12032                   [(set (v4i32 V128:$dst),
12033                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
12034                                 (v4i32 V128:$Rm)))]>;
12035
12036class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
12037  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
12038                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
12039                   [(set (v4i32 FPR128:$dst),
12040                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
12041                                 (v4i32 V128:$Rm)))]>;
12042
12043let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
12044class SHA2OpInst<bits<4> opc, string asm, string kind,
12045                 string cstr, dag oops, dag iops,
12046                 list<dag> pat>
12047  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
12048                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
12049    Sched<[WriteVq]>{
12050  bits<5> Rd;
12051  bits<5> Rn;
12052  let Inst{31-16} = 0b0101111000101000;
12053  let Inst{15-12} = opc;
12054  let Inst{11-10} = 0b10;
12055  let Inst{9-5}   = Rn;
12056  let Inst{4-0}   = Rd;
12057}
12058
12059class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
12060  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
12061               (ins V128:$Rd, V128:$Rn),
12062               [(set (v4i32 V128:$dst),
12063                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
12064
12065class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
12066  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
12067               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
12068
12069// Armv8.2-A Crypto extensions
12070class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
12071                    list<dag> pattern>
12072  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
12073  bits<5> Vd;
12074  bits<5> Vn;
12075  let Inst{31-25} = 0b1100111;
12076  let Inst{9-5}   = Vn;
12077  let Inst{4-0}   = Vd;
12078}
12079
12080class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
12081  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
12082                  "$Vd = $Vdst", []> {
12083  let Inst{31-25} = 0b1100111;
12084  let Inst{24-21} = 0b0110;
12085  let Inst{20-15} = 0b000001;
12086  let Inst{14}    = op0;
12087  let Inst{13-12} = 0b00;
12088  let Inst{11-10} = op1;
12089}
12090class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
12091  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
12092class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
12093  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
12094
12095class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
12096                string asmops, string cst>
12097  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
12098  bits<5> Vm;
12099  let Inst{24-21} = 0b0011;
12100  let Inst{20-16} = Vm;
12101  let Inst{15}    = 0b1;
12102  let Inst{14}    = op0;
12103  let Inst{13-12} = 0b00;
12104  let Inst{11-10} = op1;
12105}
12106class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
12107  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
12108              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
12109class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
12110  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
12111              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
12112class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
12113  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
12114              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
12115class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
12116  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
12117              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
12118class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
12119  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
12120              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
12121
12122class CryptoRRRR<bits<2>op0, string asm, string asmops>
12123  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
12124                  asmops, "", []> {
12125  bits<5> Vm;
12126  bits<5> Va;
12127  let Inst{24-23} = 0b00;
12128  let Inst{22-21} = op0;
12129  let Inst{20-16} = Vm;
12130  let Inst{15}    = 0b0;
12131  let Inst{14-10} = Va;
12132}
12133class CryptoRRRR_16B<bits<2>op0, string asm>
12134 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
12135                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
12136}
12137class CryptoRRRR_4S<bits<2>op0, string asm>
12138 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
12139                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
12140}
12141
12142class CryptoRRRi6<string asm>
12143  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
12144                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
12145                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
12146  bits<6> imm;
12147  bits<5> Vm;
12148  let Inst{24-21} = 0b0100;
12149  let Inst{20-16} = Vm;
12150  let Inst{15-10} = imm;
12151  let Inst{9-5}   = Vn;
12152  let Inst{4-0}   = Vd;
12153}
12154
12155class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
12156  : BaseCryptoV82<(outs V128:$Vdst),
12157                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
12158                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
12159                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
12160  bits<2> imm;
12161  bits<5> Vm;
12162  let Inst{24-21} = 0b0010;
12163  let Inst{20-16} = Vm;
12164  let Inst{15}    = 0b1;
12165  let Inst{14}    = op0;
12166  let Inst{13-12} = imm;
12167  let Inst{11-10} = op1;
12168}
12169
12170//----------------------------------------------------------------------------
12171// v8.1 atomic instructions extension:
12172// * CAS
12173// * CASP
12174// * SWP
12175// * LDOPregister<OP>, and aliases STOPregister<OP>
12176
12177// Instruction encodings:
12178//
12179//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
12180// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
12181// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
12182// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
12183// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
12184// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
12185
12186// Instruction syntax:
12187//
12188// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
12189// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
12190// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
12191// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
12192// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
12193// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
12194// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
12195// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
12196// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
12197// ST<OP>{<order>} <Xs>, [<Xn|SP>]
12198
12199let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
12200class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
12201                      string cstr, list<dag> pattern>
12202      : I<oops, iops, asm, operands, cstr, pattern> {
12203  bits<2> Sz;
12204  bit NP;
12205  bit Acq;
12206  bit Rel;
12207  bits<5> Rs;
12208  bits<5> Rn;
12209  bits<5> Rt;
12210  let Inst{31-30} = Sz;
12211  let Inst{29-24} = 0b001000;
12212  let Inst{23} = NP;
12213  let Inst{22} = Acq;
12214  let Inst{21} = 0b1;
12215  let Inst{20-16} = Rs;
12216  let Inst{15} = Rel;
12217  let Inst{14-10} = 0b11111;
12218  let Inst{9-5} = Rn;
12219  let Inst{4-0} = Rt;
12220  let Predicates = [HasLSE];
12221}
12222
12223class BaseCAS<string order, string size, RegisterClass RC>
12224      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
12225                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
12226                        "$out = $Rs",[]>,
12227        Sched<[WriteAtomic]> {
12228  let NP = 1;
12229}
12230
12231multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
12232  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
12233  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
12234  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
12235  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
12236}
12237
12238class BaseCASP<string order, string size, RegisterOperand RC>
12239      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
12240                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
12241                        "$out = $Rs",[]>,
12242        Sched<[WriteAtomic]> {
12243  let NP = 0;
12244}
12245
12246multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
12247  let Sz = 0b00, Acq = Acq, Rel = Rel in
12248    def W : BaseCASP<order, "", WSeqPairClassOperand>;
12249  let Sz = 0b01, Acq = Acq, Rel = Rel in
12250    def X : BaseCASP<order, "", XSeqPairClassOperand>;
12251}
12252
12253// v9.6-a CAST unprivileged instructions
12254let mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
12255class BaseCASTEncoding<dag oops, dag iops, string asm,
12256                      string cstr, list<dag> pattern>
12257      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", cstr, pattern> {
12258  bits<5> Rs;
12259  bits<5> Rn;
12260  bits<5> Rt;
12261  bit L;
12262  bit o0;
12263  bits<2> Sz;
12264  let Inst{31-30} = Sz;
12265  let Inst{29-23} = 0b0010011;
12266  let Inst{22} = L;
12267  let Inst{21} = 0b0;
12268  let Inst{20-16} = Rs;
12269  let Inst{15} = o0;
12270  let Inst{14-10} = 0b11111;
12271  let Unpredictable{14-10} = 0b11111;
12272  let Inst{9-5} = Rn;
12273  let Inst{4-0} = Rt;
12274}
12275
12276multiclass CompareAndSwapUnprivileged<bits<2> Sz, bit L, bit o0, string order> {
12277  let Sz = Sz, L = L, o0 = o0 in
12278    def X : BaseCASTEncoding <
12279        (outs GPR64:$out),
12280        (ins GPR64:$Rs, GPR64:$Rt, GPR64sp0:$Rn),
12281        "cas" # order # "t",
12282        "$out = $Rs",[]>, Sched<[WriteAtomic]>;
12283
12284}
12285
12286multiclass CompareAndSwapPairUnprivileged<bits<2> Sz, bit L, bit o0, string order> {
12287  let Sz = Sz, L = L, o0 = o0 in
12288    def X : BaseCASTEncoding<(outs XSeqPairClassOperand:$out),
12289            (ins XSeqPairClassOperand:$Rs, XSeqPairClassOperand:$Rt, GPR64sp0:$Rn),
12290                            "casp" # order # "t",
12291                            "$out = $Rs",[]>,
12292            Sched<[WriteAtomic]>;
12293}
12294
12295let Predicates = [HasLSE] in
12296class BaseSWP<string order, string size, RegisterClass RC>
12297      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
12298          "\t$Rs, $Rt, [$Rn]","",[]>,
12299        Sched<[WriteAtomic]> {
12300  bits<2> Sz;
12301  bit Acq;
12302  bit Rel;
12303  bits<5> Rs;
12304  bits<3> opc = 0b000;
12305  bits<5> Rn;
12306  bits<5> Rt;
12307  let Inst{31-30} = Sz;
12308  let Inst{29-24} = 0b111000;
12309  let Inst{23} = Acq;
12310  let Inst{22} = Rel;
12311  let Inst{21} = 0b1;
12312  let Inst{20-16} = Rs;
12313  let Inst{15} = 0b1;
12314  let Inst{14-12} = opc;
12315  let Inst{11-10} = 0b00;
12316  let Inst{9-5} = Rn;
12317  let Inst{4-0} = Rt;
12318  let Predicates = [HasLSE];
12319}
12320
12321multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
12322  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
12323  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
12324  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
12325  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
12326}
12327
12328// v9.6a swap operations
12329class BaseSWPLSUI<string order, RegisterClass RC>
12330       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swpt" # order,
12331           "\t$Rs, $Rt, [$Rn]","",[]>,
12332         Sched<[WriteAtomic]> {
12333   bits<2> Sz;
12334   bit Acq;
12335   bit Rel;
12336   bits<5> Rs;
12337   bits<5> Rn;
12338   bits<5> Rt;
12339   let Inst{31-30} = Sz;
12340   let Inst{29-24} = 0b011001;
12341   let Inst{23} = Acq;
12342   let Inst{22} = Rel;
12343   let Inst{21} = 0b1;
12344   let Inst{20-16} = Rs;
12345   let Inst{15} = 0b1;
12346   let Inst{14-12} = 0b000;
12347   let Inst{11-10} = 0b01;
12348   let Inst{9-5} = Rn;
12349   let Inst{4-0} = Rt;
12350}
12351
12352multiclass SwapLSUI<bits<1> Acq, bits<1> Rel, string order> {
12353  let Sz = 0b00, Acq = Acq, Rel = Rel in def W : BaseSWPLSUI<order, GPR32>;
12354  let Sz = 0b01, Acq = Acq, Rel = Rel in def X : BaseSWPLSUI<order, GPR64>;
12355}
12356
12357let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
12358class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
12359      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
12360          "\t$Rs, $Rt, [$Rn]","",[]>,
12361        Sched<[WriteAtomic]> {
12362  bits<2> Sz;
12363  bit Acq;
12364  bit Rel;
12365  bits<5> Rs;
12366  bits<3> opc;
12367  bits<5> Rn;
12368  bits<5> Rt;
12369  let Inst{31-30} = Sz;
12370  let Inst{29-24} = 0b111000;
12371  let Inst{23} = Acq;
12372  let Inst{22} = Rel;
12373  let Inst{21} = 0b1;
12374  let Inst{20-16} = Rs;
12375  let Inst{15} = 0b0;
12376  let Inst{14-12} = opc;
12377  let Inst{11-10} = 0b00;
12378  let Inst{9-5} = Rn;
12379  let Inst{4-0} = Rt;
12380  let Predicates = [HasLSE];
12381}
12382
12383multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
12384                        string order> {
12385  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
12386    def B : BaseLDOPregister<op, order, "b", GPR32>;
12387  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
12388    def H : BaseLDOPregister<op, order, "h", GPR32>;
12389  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
12390    def W : BaseLDOPregister<op, order, "", GPR32>;
12391  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
12392    def X : BaseLDOPregister<op, order, "", GPR64>;
12393}
12394
12395class BaseLDOPregisterLSUI<string op, string order, RegisterClass RC>
12396      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ldt" # op # order,
12397          "\t$Rs, $Rt, [$Rn]","",[]>,
12398        Sched<[WriteAtomic]> {
12399  bits<2> Sz;
12400  bit Acq;
12401  bit Rel;
12402  bits<5> Rs;
12403  bits<3> opc;
12404  bits<5> Rn;
12405  bits<5> Rt;
12406  let Inst{31-30} = Sz;
12407  let Inst{29-24} = 0b011001;
12408  let Inst{23} = Acq;
12409  let Inst{22} = Rel;
12410  let Inst{21} = 0b1;
12411  let Inst{20-16} = Rs;
12412  let Inst{15} = 0b0;
12413  let Inst{14-12} = opc;
12414  let Inst{11-10} = 0b01;
12415  let Inst{9-5} = Rn;
12416  let Inst{4-0} = Rt;
12417}
12418
12419
12420multiclass LDOPregisterLSUI<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
12421                        string order> {
12422  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
12423    def W : BaseLDOPregisterLSUI<op, order, GPR32>;
12424  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
12425    def X : BaseLDOPregisterLSUI<op, order, GPR64>;
12426}
12427
12428// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
12429// complex DAG for DstRHS.
12430let Predicates = [HasLSE] in
12431multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
12432                                         ValueType vt, dag SrcRHS, dag DstRHS> {
12433  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_monotonic") GPR64sp:$Rn, SrcRHS),
12434            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
12435  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acquire") GPR64sp:$Rn, SrcRHS),
12436            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
12437  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_release") GPR64sp:$Rn, SrcRHS),
12438            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
12439  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acq_rel") GPR64sp:$Rn, SrcRHS),
12440            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
12441  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_seq_cst") GPR64sp:$Rn, SrcRHS),
12442            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
12443}
12444
12445multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
12446                                     ValueType vt, dag RHS> {
12447  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, vt, RHS, RHS>;
12448}
12449
12450multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
12451                                         ValueType vt, dag LHS, dag RHS> {
12452  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, vt, LHS, RHS>;
12453}
12454
12455multiclass LDOPregister_patterns<string inst, string op> {
12456  defm : LDOPregister_patterns_ord<inst, "X", op, i64, (i64 GPR64:$Rm)>;
12457  defm : LDOPregister_patterns_ord<inst, "W", op, i32, (i32 GPR32:$Rm)>;
12458  defm : LDOPregister_patterns_ord<inst, "H", op, i16, (i32 GPR32:$Rm)>;
12459  defm : LDOPregister_patterns_ord<inst, "B", op, i8,  (i32 GPR32:$Rm)>;
12460}
12461
12462multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
12463  defm : LDOPregister_patterns_ord_mod<inst, "X", op, i64,
12464                        (i64 GPR64:$Rm),
12465                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
12466  defm : LDOPregister_patterns_ord_mod<inst, "W", op, i32,
12467                        (i32 GPR32:$Rm),
12468                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
12469  defm : LDOPregister_patterns_ord_mod<inst, "H", op, i16,
12470                        (i32 GPR32:$Rm),
12471                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
12472  defm : LDOPregister_patterns_ord_mod<inst, "B", op, i8,
12473                        (i32 GPR32:$Rm),
12474                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
12475}
12476
12477let Predicates = [HasLSE] in
12478multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
12479                                        ValueType vt, dag OLD, dag NEW> {
12480  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_monotonic") GPR64sp:$Rn, OLD, NEW),
12481            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
12482  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acquire") GPR64sp:$Rn, OLD, NEW),
12483            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
12484  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_release") GPR64sp:$Rn, OLD, NEW),
12485            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
12486  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
12487            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
12488  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
12489            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
12490}
12491
12492multiclass CASregister_patterns_ord<string inst, string suffix, string op,
12493                                    ValueType vt, dag OLD, dag NEW> {
12494  defm : CASregister_patterns_ord_dag<inst, suffix, op, vt, OLD, NEW>;
12495}
12496
12497multiclass CASregister_patterns<string inst, string op> {
12498  defm : CASregister_patterns_ord<inst, "X", op, i64,
12499                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
12500  defm : CASregister_patterns_ord<inst, "W", op, i32,
12501                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
12502  defm : CASregister_patterns_ord<inst, "H", op, i16,
12503                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
12504  defm : CASregister_patterns_ord<inst, "B", op, i8,
12505                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
12506}
12507
12508let Predicates = [HasLSE] in
12509class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
12510                        Instruction inst> :
12511      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
12512
12513multiclass STOPregister<string asm, string instr> {
12514  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
12515                    !cast<Instruction>(instr # "LB")>;
12516  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
12517                    !cast<Instruction>(instr # "LH")>;
12518  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
12519                    !cast<Instruction>(instr # "LW")>;
12520  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
12521                    !cast<Instruction>(instr # "LX")>;
12522  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
12523                    !cast<Instruction>(instr # "B")>;
12524  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
12525                    !cast<Instruction>(instr # "H")>;
12526  def : BaseSTOPregister<asm,        GPR32, WZR,
12527                    !cast<Instruction>(instr # "W")>;
12528  def : BaseSTOPregister<asm,        GPR64, XZR,
12529                    !cast<Instruction>(instr # "X")>;
12530}
12531
12532class BaseSTOPregisterLSUI<string asm, RegisterClass OP, Register Reg,
12533                        Instruction inst> :
12534      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
12535
12536multiclass STOPregisterLSUI<string asm, string instr> {
12537  def : BaseSTOPregisterLSUI<asm # "a",        GPR32, WZR,
12538                    !cast<Instruction>(instr # "W")>;
12539  def : BaseSTOPregisterLSUI<asm # "a",        GPR64, XZR,
12540                    !cast<Instruction>(instr # "X")>;
12541  def : BaseSTOPregisterLSUI<asm # "l",        GPR32, WZR,
12542                    !cast<Instruction>(instr # "W")>;
12543  def : BaseSTOPregisterLSUI<asm # "l",        GPR64, XZR,
12544                    !cast<Instruction>(instr # "X")>;
12545  def : BaseSTOPregisterLSUI<asm # "al",        GPR32, WZR,
12546                    !cast<Instruction>(instr # "W")>;
12547  def : BaseSTOPregisterLSUI<asm # "al",        GPR64, XZR,
12548                    !cast<Instruction>(instr # "X")>;
12549  def : BaseSTOPregisterLSUI<asm,        GPR32, WZR,
12550                    !cast<Instruction>(instr # "W")>;
12551  def : BaseSTOPregisterLSUI<asm,        GPR64, XZR,
12552                    !cast<Instruction>(instr # "X")>;
12553}
12554
12555class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
12556                        dag iops, dag oops, list<dag> pat>
12557    : I<oops, iops, asm_inst, asm_ops, "", pat>,
12558      Sched<[]> /* FIXME: fill in scheduling details once known */ {
12559  bits<5> Rt;
12560  bits<5> Rn;
12561  let Inst{31-21} = 0b11111000001;
12562  let Inst{15}    = 1;
12563  let Inst{14-12} = opc;
12564  let Inst{11-10} = 0b00;
12565  let Inst{9-5}   = Rn;
12566  let Inst{4-0}   = Rt;
12567
12568  let Predicates = [HasV8_7a];
12569}
12570
12571class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
12572                      list<dag> pat = []>
12573    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
12574  let Inst{20-16} = 0b11111;
12575}
12576
12577class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
12578    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
12579                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
12580  bits<5> Rs;
12581  let Inst{20-16} = Rs;
12582  let mayStore = 1;
12583}
12584
12585class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
12586                             bits<2> op2, string asm>
12587  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
12588      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
12589      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
12590      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
12591    Sched<[]> {
12592  bits<5> Rd;
12593  bits<5> Rs;
12594  bits<5> Rn;
12595  let Inst{31-27} = 0b00011;
12596  let Inst{26} = isMove;
12597  let Inst{25-24} = 0b01;
12598  let Inst{23-22} = opcode;
12599  let Inst{21} = 0b0;
12600  let Inst{20-16} = Rs;
12601  let Inst{15-14} = op2;
12602  let Inst{13-12} = op1;
12603  let Inst{11-10} = 0b01;
12604  let Inst{9-5} = Rn;
12605  let Inst{4-0} = Rd;
12606
12607  let DecoderMethod = "DecodeCPYMemOpInstruction";
12608  let mayLoad = 1;
12609  let mayStore = 1;
12610}
12611
12612class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12613  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
12614
12615class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12616  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
12617
12618class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
12619                        string asm>
12620  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
12621      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
12622      asm, "\t[$Rd]!, $Rn!, $Rm",
12623      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
12624    Sched<[]> {
12625  bits<5> Rd;
12626  bits<5> Rn;
12627  bits<5> Rm;
12628  let Inst{31-27} = 0b00011;
12629  let Inst{26} = isTagging;
12630  let Inst{25-21} = 0b01110;
12631  let Inst{20-16} = Rm;
12632  let Inst{15-14} = opcode;
12633  let Inst{13} = op2;
12634  let Inst{12} = op1;
12635  let Inst{11-10} = 0b01;
12636  let Inst{9-5} = Rn;
12637  let Inst{4-0} = Rd;
12638
12639  let DecoderMethod = "DecodeSETMemOpInstruction";
12640  let mayLoad = 0;
12641  let mayStore = 1;
12642}
12643
12644class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
12645  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
12646
12647class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
12648  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
12649
12650multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
12651  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
12652  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
12653  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
12654  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
12655  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
12656  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
12657  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
12658  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
12659  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
12660  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
12661  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
12662  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
12663  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
12664  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
12665  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
12666  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
12667}
12668
12669multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
12670  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
12671  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
12672  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
12673  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
12674  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
12675  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
12676  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
12677  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
12678  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
12679  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
12680  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
12681  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
12682  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
12683  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
12684  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
12685  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
12686}
12687
12688multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
12689  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
12690  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
12691  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
12692  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
12693}
12694
12695multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
12696  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
12697  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
12698  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
12699  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
12700}
12701
12702//----------------------------------------------------------------------------
12703// 2022 Armv8.9/Armv9.4 Extensions
12704//----------------------------------------------------------------------------
12705
12706//---
12707// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
12708//---
12709
12710class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
12711                           RegisterClass regtype, ImmLeaf immtype, string asm,
12712                           SDPatternOperator OpNode>
12713    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
12714        asm, "\t$Rd, $Rn, $imm", "",
12715        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
12716  bits<5> Rd;
12717  bits<5> Rn;
12718  bits<8> imm;
12719
12720  let Inst{31}    = sf;
12721  let Inst{30}    = Op;
12722  let Inst{29}    = S;
12723  let Inst{28-22} = 0b1000111;
12724  let Inst{21-18} = opc;
12725  let Inst{17-10} = imm;
12726  let Inst{9-5}   = Rn;
12727  let Inst{4-0}   = Rd;
12728}
12729
12730class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
12731                          RegisterClass regtype, string asm,
12732                          SDPatternOperator OpNode>
12733    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
12734      Sched<[WriteI]> {
12735  let Inst{11} = isMin;
12736  let Inst{10} = isUnsigned;
12737  let mayLoad  = 0;
12738  let mayStore = 0;
12739  let hasSideEffects = 0;
12740}
12741
12742class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
12743                          RegisterClass regtype, ImmLeaf immtype, string asm,
12744                          SDPatternOperator OpNode>
12745    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
12746                           OpNode>,
12747      Sched<[]> {
12748  let Inst{19} = isMin;
12749  let Inst{18} = isUnsigned;
12750  let mayLoad  = 0;
12751  let mayStore = 0;
12752  let hasSideEffects = 0;
12753}
12754
12755multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
12756                        SDPatternOperator OpNode = null_frag> {
12757  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
12758
12759  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
12760                                !cond(isUnsigned : uimm8_32b,
12761                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
12762
12763  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
12764
12765  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
12766                                !cond(isUnsigned : uimm8_64b,
12767                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
12768}
12769
12770//---
12771// RCPC instructions (FEAT_LRCPC3)
12772//---
12773
12774class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
12775                 string asm, string operands, string cstr = "">
12776      : I<oops, iops, asm, operands, cstr, []>,
12777        Sched<[WriteAtomic]> {
12778  bits<5> Rt;
12779  bits<5> Rn;
12780  let Inst{31-30}    = size;
12781  let Inst{29-24}    = {0,1,1,V,0,1};
12782  let Inst{23-22}    = opc;
12783  let Inst{21}       = 0b0;
12784  //  Inst{20-12}
12785  let Inst{11-10}    = 0b10;
12786  let Inst{9-5}      = Rn;
12787  let Inst{4-0}      = Rt;
12788
12789  let mayLoad = Inst{22};
12790  let mayStore = !not(Inst{22});
12791  let hasSideEffects = 0;
12792}
12793
12794class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
12795                                     dag oops, dag iops, string asm,
12796                                     string operands, string cstr>
12797      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12798  bits<5> Rt2;
12799  let Inst{20-16} = Rt2;
12800  let Inst{15-12} = opc2;
12801}
12802
12803class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
12804                                 string asm, string operands, string cstr>
12805      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12806  let Inst{20-12} = 0b000000000; // imm9
12807}
12808
12809multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
12810                                             dag oops, dag iops, string asm> {
12811  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
12812    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
12813    let Inst{20-12} = simm;
12814  }
12815
12816  def a : InstAlias<asm # "\t$Rt, [$Rn]",
12817                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
12818}
12819
12820class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
12821      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
12822                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
12823        Sched<[]> {
12824  bit Q;
12825  let Inst{31}       = 0;
12826  let Inst{30}       = Q;
12827  let Inst{23}       = 0;
12828  let Inst{20-16}    = 0b00001;
12829  let Inst{12}       = 0; // S
12830  let Inst{11-10}    = 0b01; // size
12831
12832  let mayLoad = L;
12833  let mayStore = !not(L);
12834  let hasSideEffects = 1;
12835}
12836
12837//---
12838// Instrumentation Extension (FEAT_ITE)
12839//---
12840
12841let Predicates = [HasITE] in
12842def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
12843  let Inst{20-19} = 0b01;
12844  let Inst{18-16} = 0b011;
12845  let Inst{15-12} = 0b0111;
12846  let Inst{11-8}  = 0b0010;
12847  let Inst{7-5}   = 0b111;
12848}
12849
12850// * RCWCAS family
12851// * RCW<OP> family
12852
12853//--------------------------------------------------------------------
12854// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
12855
12856// Instruction encoding:
12857//
12858//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
12859// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12860// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12861// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12862// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12863
12864// Instruction syntax:
12865//
12866// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
12867// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
12868
12869class BaseRCWCASEncoding<dag oops, dag iops, string asm>
12870      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
12871        Sched<[]> {
12872  bit Acq;
12873  bit Rel;
12874  bit SC;
12875  bit Pair;
12876  bits<5> Rs;
12877  bits<5> Rn;
12878  bits<5> Rt;
12879  let Inst{31} = 0b0;
12880  let Inst{30} = SC;
12881  let Inst{29-24} = 0b011001;
12882  let Inst{23} = Acq;
12883  let Inst{22} = Rel;
12884  let Inst{21} = 0b1;
12885  let Inst{20-16} = Rs;
12886  let Inst{15-13} = 0b000;
12887  let Inst{12-11} = 0b01;
12888  let Inst{10} = Pair;
12889  let Inst{9-5} = Rn;
12890  let Inst{4-0} = Rt;
12891  let mayLoad = 1;
12892  let mayStore = 1;
12893  let hasSideEffects = 1;
12894  let Defs = [NZCV];
12895}
12896
12897multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
12898  let Acq = 0b0, Rel = 0b0 in
12899    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
12900  let Acq = 0b1, Rel = 0b0 in
12901    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
12902  let Acq = 0b0, Rel = 0b1 in
12903    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
12904  let Acq = 0b1, Rel = 0b1 in
12905    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
12906}
12907
12908multiclass ReadCheckWriteCompareAndSwap {
12909  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
12910    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
12911                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
12912  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
12913    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
12914                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
12915  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12916    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12917                           (ins XSeqPairClassOperand:$Rs,
12918                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12919                           "rcwcasp">;
12920  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12921    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12922                           (ins XSeqPairClassOperand:$Rs,
12923                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12924                           "rcwscasp">;
12925}
12926
12927//------------------------------------------------------------------
12928// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
12929
12930// Instruction encoding:
12931//
12932//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12933// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12934// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12935// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12936// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12937// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12938// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12939
12940//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12941// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12942// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12943// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12944// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12945// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12946// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12947
12948// Instruction syntax:
12949//
12950// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
12951// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
12952
12953class BaseRCWOPEncoding<string asm>
12954      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
12955          "\t$Rs, $Rt, [$Rn]", "", []>,
12956        Sched<[]> {
12957  bit Acq;
12958  bit Rel;
12959  bit SC;
12960  bits<3> opc;
12961  bits<5> Rs;
12962  bits<5> Rn;
12963  bits<5> Rt;
12964  let Inst{31} = 0b0;
12965  let Inst{30} = SC;
12966  let Inst{29-24} = 0b111000;
12967  let Inst{23} = Acq;
12968  let Inst{22} = Rel;
12969  let Inst{21} = 0b1;
12970  let Inst{20-16} = Rs;
12971  let Inst{15} = 0b1;
12972  let Inst{14-12} = opc;
12973  let Inst{11-10} = 0b00;
12974  let Inst{9-5} = Rn;
12975  let Inst{4-0} = Rt;
12976  let mayLoad = 1;
12977  let mayStore = 1;
12978  let hasSideEffects = 1;
12979  let Defs = [NZCV];
12980  let Predicates = [HasTHE];
12981}
12982
12983class BaseRCWOPPEncoding<string asm>
12984      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12985          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12986          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12987        Sched<[]> {
12988  bit Acq;
12989  bit Rel;
12990  bit SC;
12991  bits<3> opc;
12992  bits<5> Rt2;
12993  bits<5> Rn;
12994  bits<5> Rt;
12995  let Inst{31} = 0b0;
12996  let Inst{30} = SC;
12997  let Inst{29-24} = 0b011001;
12998  let Inst{23} = Acq;
12999  let Inst{22} = Rel;
13000  let Inst{21} = 0b1;
13001  let Inst{20-16} = Rt2;
13002  let Inst{15} = 0b1;
13003  let Inst{14-12} = opc;
13004  let Inst{11-10} = 0b00;
13005  let Inst{9-5} = Rn;
13006  let Inst{4-0} = Rt;
13007  let mayLoad = 1;
13008  let mayStore = 1;
13009  let hasSideEffects = 1;
13010  let Defs = [NZCV];
13011  let Predicates = [HasTHE, HasD128];
13012}
13013
13014multiclass BaseRCWOP<string prefix> {
13015  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
13016  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
13017  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
13018  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
13019
13020  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
13021  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
13022  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
13023  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
13024}
13025
13026multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
13027  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
13028  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
13029}
13030
13031//---
13032// 128-bit atomic instructions (FEAT_LSE128)
13033//---
13034
13035let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
13036class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
13037: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
13038    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
13039    asm, "\t$Rt, $Rt2, [$Rn]",
13040    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
13041  Sched<[]> {
13042  bits<5> Rt;
13043  bits<5> Rt2;
13044  bits<5> Rn;
13045  let Inst{31-24} = 0b00011001;
13046  let Inst{23-22} = AR;
13047  let Inst{21} = 0b1;
13048  let Inst{20-16} = Rt2;
13049  let Inst{15} = o3;
13050  let Inst{14-12} = op0;
13051  let Inst{11-10} = 0b00;
13052  let Inst{9-5} = Rn;
13053  let Inst{4-0} = Rt;
13054}
13055
13056//---
13057// 128-bit System Instructions (FEAT_SYSINSTR128)
13058//---
13059
13060// Instruction encoding:
13061//
13062//          31          19|18 16|15 12|11 8|7 5|4 0
13063// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
13064
13065// Instruction syntax:
13066//
13067// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
13068
13069class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
13070  RtSystemI<L, oops, iops, asm, operands, pattern> {
13071  let Inst{22}    = 0b1; // override BaseSystemI
13072}
13073
13074class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
13075  : RtSystemI128<L, outputs, inputs, asm, operands> {
13076  bits<3> op1;
13077  bits<4> Cn;
13078  bits<4> Cm;
13079  bits<3> op2;
13080  let Inst{20-19} = 0b01;
13081  let Inst{18-16} = op1;
13082  let Inst{15-12} = Cn;
13083  let Inst{11-8}  = Cm;
13084  let Inst{7-5}   = op2;
13085}
13086class SystemPXtI<bit L, string asm> :
13087  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
13088  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
13089
13090//----------------------------------------------------------------------------
13091// 2023 Armv9.5 Extensions
13092//----------------------------------------------------------------------------
13093
13094//---
13095// Checked Pointer Arithmetic (FEAT_CPA)
13096//---
13097
13098def LSLImm3ShiftOperand : AsmOperandClass {
13099  let SuperClasses = [ExtendOperandLSL64];
13100  let Name = "LSLImm3Shift";
13101  let RenderMethod = "addLSLImm3ShifterOperands";
13102  let DiagnosticType = "AddSubLSLImm3ShiftLarge";
13103}
13104
13105def lsl_imm3_shift_operand : Operand<i32> {
13106  let PrintMethod = "printShifter";
13107  let ParserMatchClass = LSLImm3ShiftOperand;
13108}
13109
13110// Base CPA scalar add/subtract with lsl #imm3 shift
13111class BaseAddSubCPA<bit isSub, string asm> : I<(outs GPR64sp:$Rd),
13112    (ins GPR64sp:$Rn, GPR64:$Rm, lsl_imm3_shift_operand:$shift_imm),
13113    asm, "\t$Rd, $Rn, $Rm$shift_imm", "", []>, Sched<[]> {
13114  bits<5> Rd;
13115  bits<5> Rn;
13116  bits<5> Rm;
13117  bits<3> shift_imm;
13118  let Inst{31} = 0b1;
13119  let Inst{30} = isSub;
13120  let Inst{29-21} = 0b011010000;
13121  let Inst{20-16} = Rm;
13122  let Inst{15-13} = 0b001;
13123  let Inst{12-10} = shift_imm;
13124  let Inst{9-5} = Rn;
13125  let Inst{4-0} = Rd;
13126}
13127
13128// Alias for CPA scalar add/subtract with no shift
13129class AddSubCPAAlias<string asm, Instruction inst>
13130    : InstAlias<asm#"\t$Rd, $Rn, $Rm",
13131                (inst GPR64sp:$Rd, GPR64sp:$Rn, GPR64:$Rm, 0)>;
13132
13133multiclass AddSubCPA<bit isSub, string asm> {
13134  def _shift : BaseAddSubCPA<isSub, asm>;
13135  def _noshift : AddSubCPAAlias<asm, !cast<Instruction>(NAME#"_shift")>;
13136}
13137
13138class MulAccumCPA<bit isSub, string asm>
13139  : BaseMulAccum<isSub, 0b011, GPR64, GPR64, asm, []>, Sched<[]> {
13140  let Inst{31} = 0b1;
13141}
13142
13143
13144//----------------------------------------------------------------------------
13145// 2024 Armv9.6 Extensions
13146//----------------------------------------------------------------------------
13147
13148//---
13149// Compare-and-branch instructions.
13150//---
13151
13152class BaseCmpBranchRegister<RegisterClass regtype, bit sf, bits<3> cc,
13153                            bits<2>sz, string asm>
13154    : I<(outs), (ins regtype:$Rt, regtype:$Rm, am_brcmpcond:$target),
13155         asm, "\t$Rt, $Rm, $target", "",
13156         []>,
13157      Sched<[WriteBr]> {
13158  let isBranch = 1;
13159  let isTerminator = 1;
13160
13161  bits<5> Rm;
13162  bits<5> Rt;
13163  bits<9> target;
13164  let Inst{31}    = sf;
13165  let Inst{30-24} = 0b1110100;
13166  let Inst{23-21} = cc;
13167  let Inst{20-16} = Rm;
13168  let Inst{15-14} = sz;
13169  let Inst{13-5}  = target;
13170  let Inst{4-0}   = Rt;
13171}
13172
13173multiclass CmpBranchRegister<bits<3> cc, string asm> {
13174  def Wrr : BaseCmpBranchRegister<GPR32, 0b0, cc, 0b00, asm>;
13175  def Xrr : BaseCmpBranchRegister<GPR64, 0b1, cc, 0b00, asm>;
13176}
13177
13178class BaseCmpBranchImmediate<RegisterClass regtype, bit sf, bits<3> cc,
13179                             Operand imm_ty, string asm>
13180    : I<(outs), (ins regtype:$Rt, imm_ty:$imm, am_brcmpcond:$target),
13181         asm, "\t$Rt, $imm, $target", "",
13182         []>,
13183      Sched<[WriteBr]> {
13184  let isBranch = 1;
13185  let isTerminator = 1;
13186
13187  bits<5> Rt;
13188  bits<6> imm;
13189  bits<9> target;
13190  let Inst{31}    = sf;
13191  let Inst{30-24} = 0b1110101;
13192  let Inst{23-21} = cc;
13193  let Inst{20-15} = imm;
13194  let Inst{14}    = 0b0;
13195  let Inst{13-5}  = target;
13196  let Inst{4-0}   = Rt;
13197}
13198
13199multiclass CmpBranchImmediate<bits<3> cc, string imm_ty, string asm> {
13200  def Wri : BaseCmpBranchImmediate<GPR32, 0b0, cc, !cast<Operand>(imm_ty # "_32b"), asm>;
13201  def Xri : BaseCmpBranchImmediate<GPR64, 0b1, cc, !cast<Operand>(imm_ty # "_64b"), asm>;
13202}
13203
13204multiclass CmpBranchImmediateAlias<string mnemonic, string insn, string imm_ty> {
13205 def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
13206                 (!cast<Instruction>(insn # "Wri") GPR32:$Rt,
13207                  !cast<Operand>(imm_ty # "_32b"):$imm,
13208                  am_brcmpcond:$target), 0>;
13209 def : InstAlias<mnemonic # "\t$Rt, $imm, $target",
13210                 (!cast<Instruction>(insn # "Xri") GPR64:$Rt,
13211                  !cast<Operand>(imm_ty # "_64b"):$imm,
13212                  am_brcmpcond:$target), 0>;
13213}
13214
13215multiclass CmpBranchWRegisterAlias<string mnemonic, string insn> {
13216  def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
13217                 (!cast<Instruction>(insn # "Wrr") GPR32:$Rm, GPR32:$Rt, am_brcmpcond:$target), 0>;
13218}
13219
13220multiclass CmpBranchRegisterAlias<string mnemonic, string insn> {
13221  defm : CmpBranchWRegisterAlias<mnemonic, insn>;
13222
13223  def : InstAlias<mnemonic # "\t$Rt, $Rm, $target",
13224                 (!cast<Instruction>(insn # "Xrr") GPR64:$Rm, GPR64:$Rt, am_brcmpcond:$target), 0>;
13225}
13226//----------------------------------------------------------------------------
13227// Allow the size specifier tokens to be upper case, not just lower.
13228def : TokenAlias<".4B", ".4b">;  // Add dot product
13229def : TokenAlias<".8B", ".8b">;
13230def : TokenAlias<".4H", ".4h">;
13231def : TokenAlias<".2S", ".2s">;
13232def : TokenAlias<".1D", ".1d">;
13233def : TokenAlias<".16B", ".16b">;
13234def : TokenAlias<".8H", ".8h">;
13235def : TokenAlias<".4S", ".4s">;
13236def : TokenAlias<".2D", ".2d">;
13237def : TokenAlias<".1Q", ".1q">;
13238def : TokenAlias<".2H", ".2h">;
13239def : TokenAlias<".2B", ".2b">;
13240def : TokenAlias<".B", ".b">;
13241def : TokenAlias<".H", ".h">;
13242def : TokenAlias<".S", ".s">;
13243def : TokenAlias<".D", ".d">;
13244def : TokenAlias<".Q", ".q">;
13245
13246//----------------------------------------------------------------------------
13247// 2024 Armv9.6 Extensions
13248//----------------------------------------------------------------------------
13249
13250let mayLoad = 1, mayStore = 1 in
13251class BaseAtomicFPLoad<RegisterClass regtype, bits<2> sz, bits<2> AR,
13252                     bits<3> op0, string asm>
13253: I<(outs regtype:$Rt),
13254    (ins regtype:$Rs, GPR64sp:$Rn),
13255    asm, "\t$Rs, $Rt, [$Rn]","", []>,
13256  Sched<[]> {
13257  bits<5> Rt;
13258  bits<5> Rs;
13259  bits<5> Rn;
13260  let Inst{31-30} = sz;
13261  let Inst{29-24} = 0b111100;
13262  let Inst{23-22} = AR;
13263  let Inst{21}    = 0b1;
13264  let Inst{20-16} = Rs;
13265  let Inst{15}    = 0b0;
13266  let Inst{14-12} = op0;
13267  let Inst{11-10} = 0b00;
13268  let Inst{9-5}   = Rn;
13269  let Inst{4-0}   = Rt;
13270}
13271
13272multiclass AtomicFPLoad<bits<2> AR, bits<3> op0, string asm> {
13273  def D : BaseAtomicFPLoad<FPR64, 0b11, AR, op0, asm>;
13274  def S : BaseAtomicFPLoad<FPR32, 0b10, AR, op0, asm>;
13275  def H : BaseAtomicFPLoad<FPR16, 0b01, AR, op0, asm>;
13276}
13277
13278let mayLoad = 1, mayStore = 1 in
13279class BaseAtomicFPStore<RegisterClass regtype, bits<2> sz, bit R,
13280                      bits<3> op0, string asm>
13281: I<(outs),
13282    (ins  regtype:$Rs, GPR64sp:$Rn),
13283    asm, "\t$Rs,  [$Rn]",
13284    "", []>,
13285  Sched<[]> {
13286  bits<5> Rt;
13287  bits<5> Rs;
13288  bits<5> Rn;
13289  let Inst{31-30} = sz;
13290  let Inst{29-23} = 0b1111000;
13291  let Inst{22}    = R;
13292  let Inst{21}    = 0b1;
13293  let Inst{20-16} = Rs;
13294  let Inst{15}    = 0b1;
13295  let Inst{14-12} = op0;
13296  let Inst{11-10} = 0b00;
13297  let Inst{9-5}   = Rn;
13298  let Inst{4-0}   = 0b11111;
13299}
13300
13301multiclass AtomicFPStore<bit R, bits<3> op0, string asm> {
13302  def D : BaseAtomicFPStore<FPR64, 0b11, R, op0, asm>;
13303  def S : BaseAtomicFPStore<FPR32, 0b10, R, op0, asm>;
13304  def H : BaseAtomicFPStore<FPR16, 0b01, R, op0, asm>;
13305}
13306
13307class BaseSIMDThreeSameVectorFP8MatrixMul<string asm, bits<2> size, string kind>
13308  : BaseSIMDThreeSameVectorTied<1, 1, {size, 0}, 0b11101,
13309                                V128, asm, ".16b", []> {
13310  let AsmString = !strconcat(asm, "{\t$Rd", kind, ", $Rn", ".16b",
13311                                    ", $Rm", ".16b", "}");
13312}
13313
13314multiclass SIMDThreeSameVectorFP8MatrixMul<string asm>{
13315    def v8f16: BaseSIMDThreeSameVectorFP8MatrixMul<asm, 0b00, ".8h">{
13316      let Predicates = [HasNEON, HasF8F16MM];
13317    }
13318    def v4f32: BaseSIMDThreeSameVectorFP8MatrixMul<asm, 0b10, ".4s">{
13319      let Predicates = [HasNEON, HasF8F32MM];
13320    }
13321}
13322
13323