Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / AArch64 / AArch64InstrFormats.td
bloba5428788417f452f39b3764b63f6bbe000591142
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 //===----------------------------------------------------------------------===//
9 //===----------------------------------------------------------------------===//
10 //  Describe AArch64 instructions format here
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.
16 class Format<bits<2> val> {
17   bits<2> Value = val;
20 def PseudoFrm   : Format<0>;
21 def NormalFrm   : Format<1>; // Do we need any others?
23 // AArch64 Instruction Format
24 class AArch64Inst<Format f, string cstr> : Instruction {
25   field bits<32> Inst; // Instruction encoding.
26   // Mask of bits that cause an encoding to be UNPREDICTABLE.
27   // If a bit is set, then if the corresponding bit in the
28   // target encoding differs from its value in the "Inst" field,
29   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
30   field bits<32> Unpredictable = 0;
31   // SoftFail is the generic name for this field, but we alias it so
32   // as to make it more obvious what it means in ARM-land.
33   field bits<32> SoftFail = Unpredictable;
34   let Namespace   = "AArch64";
35   Format F        = f;
36   bits<2> Form    = F.Value;
37   let Pattern     = [];
38   let Constraints = cstr;
41 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
42   : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
44 // Pseudo instructions (don't have encoding information)
45 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
46     : AArch64Inst<PseudoFrm, cstr> {
47   dag OutOperandList = oops;
48   dag InOperandList  = iops;
49   let Pattern        = pattern;
50   let isCodeGenOnly  = 1;
53 // Real instructions (have encoding information)
54 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
55   let Pattern = pattern;
56   let Size = 4;
59 // Enum describing whether an instruction is
60 // destructive in its first source operand.
61 class DestructiveInstTypeEnum<bits<1> val> {
62   bits<1> Value = val;
64 def NotDestructive  : DestructiveInstTypeEnum<0>;
65 def Destructive     : DestructiveInstTypeEnum<1>;
67 // Normal instructions
68 class I<dag oops, dag iops, string asm, string operands, string cstr,
69         list<dag> pattern>
70     : EncodedI<cstr, pattern> {
71   dag OutOperandList = oops;
72   dag InOperandList  = iops;
73   let AsmString      = !strconcat(asm, operands);
75   // Destructive operations (SVE)
76   DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
77   ElementSizeEnum ElementSize = ElementSizeB;
79   let TSFlags{3} = DestructiveInstType.Value;
80   let TSFlags{2-0} = ElementSize.Value;
83 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
84 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
85 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
87 // Helper fragment for an extract of the high portion of a 128-bit vector.
88 def extract_high_v16i8 :
89    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
90 def extract_high_v8i16 :
91    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
92 def extract_high_v4i32 :
93    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
94 def extract_high_v2i64 :
95    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
97 //===----------------------------------------------------------------------===//
98 // Asm Operand Classes.
101 // Shifter operand for arithmetic shifted encodings.
102 def ShifterOperand : AsmOperandClass {
103   let Name = "Shifter";
106 // Shifter operand for mov immediate encodings.
107 def MovImm32ShifterOperand : AsmOperandClass {
108   let SuperClasses = [ShifterOperand];
109   let Name = "MovImm32Shifter";
110   let RenderMethod = "addShifterOperands";
111   let DiagnosticType = "InvalidMovImm32Shift";
113 def MovImm64ShifterOperand : AsmOperandClass {
114   let SuperClasses = [ShifterOperand];
115   let Name = "MovImm64Shifter";
116   let RenderMethod = "addShifterOperands";
117   let DiagnosticType = "InvalidMovImm64Shift";
120 // Shifter operand for arithmetic register shifted encodings.
121 class ArithmeticShifterOperand<int width> : AsmOperandClass {
122   let SuperClasses = [ShifterOperand];
123   let Name = "ArithmeticShifter" # width;
124   let PredicateMethod = "isArithmeticShifter<" # width # ">";
125   let RenderMethod = "addShifterOperands";
126   let DiagnosticType = "AddSubRegShift" # width;
129 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
130 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
132 // Shifter operand for logical register shifted encodings.
133 class LogicalShifterOperand<int width> : AsmOperandClass {
134   let SuperClasses = [ShifterOperand];
135   let Name = "LogicalShifter" # width;
136   let PredicateMethod = "isLogicalShifter<" # width # ">";
137   let RenderMethod = "addShifterOperands";
138   let DiagnosticType = "AddSubRegShift" # width;
141 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
142 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
144 // Shifter operand for logical vector 128/64-bit shifted encodings.
145 def LogicalVecShifterOperand : AsmOperandClass {
146   let SuperClasses = [ShifterOperand];
147   let Name = "LogicalVecShifter";
148   let RenderMethod = "addShifterOperands";
150 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
151   let SuperClasses = [LogicalVecShifterOperand];
152   let Name = "LogicalVecHalfWordShifter";
153   let RenderMethod = "addShifterOperands";
156 // The "MSL" shifter on the vector MOVI instruction.
157 def MoveVecShifterOperand : AsmOperandClass {
158   let SuperClasses = [ShifterOperand];
159   let Name = "MoveVecShifter";
160   let RenderMethod = "addShifterOperands";
163 // Extend operand for arithmetic encodings.
164 def ExtendOperand : AsmOperandClass {
165   let Name = "Extend";
166   let DiagnosticType = "AddSubRegExtendLarge";
168 def ExtendOperand64 : AsmOperandClass {
169   let SuperClasses = [ExtendOperand];
170   let Name = "Extend64";
171   let DiagnosticType = "AddSubRegExtendSmall";
173 // 'extend' that's a lsl of a 64-bit register.
174 def ExtendOperandLSL64 : AsmOperandClass {
175   let SuperClasses = [ExtendOperand];
176   let Name = "ExtendLSL64";
177   let RenderMethod = "addExtend64Operands";
178   let DiagnosticType = "AddSubRegExtendLarge";
181 // 8-bit floating-point immediate encodings.
182 def FPImmOperand : AsmOperandClass {
183   let Name = "FPImm";
184   let ParserMethod = "tryParseFPImm<true>";
185   let DiagnosticType = "InvalidFPImm";
188 def CondCode : AsmOperandClass {
189   let Name = "CondCode";
190   let DiagnosticType = "InvalidCondCode";
193 // A 32-bit register pasrsed as 64-bit
194 def GPR32as64Operand : AsmOperandClass {
195   let Name = "GPR32as64";
196   let ParserMethod =
197       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
199 def GPR32as64 : RegisterOperand<GPR32> {
200   let ParserMatchClass = GPR32as64Operand;
203 // A 64-bit register pasrsed as 32-bit
204 def GPR64as32Operand : AsmOperandClass {
205   let Name = "GPR64as32";
206   let ParserMethod =
207       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
209 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
210   let ParserMatchClass = GPR64as32Operand;
213 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
214 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
215 // are encoded as the eight bit value 'abcdefgh'.
216 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
218 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
219   let Name = "UImm" # Width # "s" # Scale;
220   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
221   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
222   let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
225 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
226   let Name = "SImm" # Width # "s" # Scale;
227   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
228   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
229   let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
232 //===----------------------------------------------------------------------===//
233 // Operand Definitions.
236 // ADR[P] instruction labels.
237 def AdrpOperand : AsmOperandClass {
238   let Name = "AdrpLabel";
239   let ParserMethod = "tryParseAdrpLabel";
240   let DiagnosticType = "InvalidLabel";
242 def adrplabel : Operand<i64> {
243   let EncoderMethod = "getAdrLabelOpValue";
244   let PrintMethod = "printAdrpLabel";
245   let ParserMatchClass = AdrpOperand;
248 def AdrOperand : AsmOperandClass {
249   let Name = "AdrLabel";
250   let ParserMethod = "tryParseAdrLabel";
251   let DiagnosticType = "InvalidLabel";
253 def adrlabel : Operand<i64> {
254   let EncoderMethod = "getAdrLabelOpValue";
255   let ParserMatchClass = AdrOperand;
258 class SImmOperand<int width> : AsmOperandClass {
259   let Name = "SImm" # width;
260   let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
261   let RenderMethod = "addImmOperands";
262   let PredicateMethod = "isSImm<" # width # ">";
266 class AsmImmRange<int Low, int High> : AsmOperandClass {
267   let Name = "Imm" # Low # "_" # High;
268   let DiagnosticType = "InvalidImm" # Low # "_" # High;
269   let RenderMethod = "addImmOperands";
270   let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
273 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
274 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
275 def simm10Scaled : Operand<i64> {
276   let ParserMatchClass = SImm10s8Operand;
277   let DecoderMethod = "DecodeSImm<10>";
278   let PrintMethod = "printImmScale<8>";
281 def simm9s16 : Operand<i64> {
282   let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
283   let DecoderMethod = "DecodeSImm<9>";
284   let PrintMethod = "printImmScale<16>";
287 // uimm6 predicate - True if the immediate is in the range [0, 63].
288 def UImm6Operand : AsmOperandClass {
289   let Name = "UImm6";
290   let DiagnosticType = "InvalidImm0_63";
293 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
294   let ParserMatchClass = UImm6Operand;
297 def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
298   let ParserMatchClass = AsmImmRange<0, 65535>;
301 def SImm9Operand : SImmOperand<9>;
302 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
303   let ParserMatchClass = SImm9Operand;
304   let DecoderMethod = "DecodeSImm<9>";
307 def SImm8Operand : SImmOperand<8>;
308 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
309   let ParserMatchClass = SImm8Operand;
310   let DecoderMethod = "DecodeSImm<8>";
313 def SImm6Operand : SImmOperand<6>;
314 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
315   let ParserMatchClass = SImm6Operand;
316   let DecoderMethod = "DecodeSImm<6>";
319 def SImm5Operand : SImmOperand<5>;
320 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
321   let ParserMatchClass = SImm5Operand;
322   let DecoderMethod = "DecodeSImm<5>";
325 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
326   let ParserMatchClass = SImm5Operand;
327   let DecoderMethod = "DecodeSImm<5>";
330 // simm7sN predicate - True if the immediate is a multiple of N in the range
331 // [-64 * N, 63 * N].
333 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
334 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
335 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
337 def simm7s4 : Operand<i32> {
338   let ParserMatchClass = SImm7s4Operand;
339   let PrintMethod = "printImmScale<4>";
342 def simm7s8 : Operand<i32> {
343   let ParserMatchClass = SImm7s8Operand;
344   let PrintMethod = "printImmScale<8>";
347 def simm7s16 : Operand<i32> {
348   let ParserMatchClass = SImm7s16Operand;
349   let PrintMethod = "printImmScale<16>";
352 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
353 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
354 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
355 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
356 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
358 // uimm5sN predicate - True if the immediate is a multiple of N in the range
359 // [0 * N, 32 * N].
360 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
361 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
362 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
364 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
365                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
366   let ParserMatchClass = UImm5s2Operand;
367   let PrintMethod = "printImmScale<2>";
369 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
370                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
371   let ParserMatchClass = UImm5s4Operand;
372   let PrintMethod = "printImmScale<4>";
374 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
375                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
376   let ParserMatchClass = UImm5s8Operand;
377   let PrintMethod = "printImmScale<8>";
380 // uimm6sN predicate - True if the immediate is a multiple of N in the range
381 // [0 * N, 64 * N].
382 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
383 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
384 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
385 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
386 def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
388 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
389   let ParserMatchClass = UImm6s1Operand;
391 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
392 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
393   let PrintMethod = "printImmScale<2>";
394   let ParserMatchClass = UImm6s2Operand;
396 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
397 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
398   let PrintMethod = "printImmScale<4>";
399   let ParserMatchClass = UImm6s4Operand;
401 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
402 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
403   let PrintMethod = "printImmScale<8>";
404   let ParserMatchClass = UImm6s8Operand;
406 def uimm6s16 : Operand<i64>, ImmLeaf<i64,
407 [{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
408   let PrintMethod = "printImmScale<16>";
409   let ParserMatchClass = UImm6s16Operand;
412 // simm6sN predicate - True if the immediate is a multiple of N in the range
413 // [-32 * N, 31 * N].
414 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
415 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
416   let ParserMatchClass = SImm6s1Operand;
417   let DecoderMethod = "DecodeSImm<6>";
420 // simm4sN predicate - True if the immediate is a multiple of N in the range
421 // [ -8* N, 7 * N].
422 def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
423 def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
424 def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
425 def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
426 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
428 def simm4s1 : Operand<i64>, ImmLeaf<i64,
429 [{ return Imm >=-8  && Imm <= 7; }]> {
430   let ParserMatchClass = SImm4s1Operand;
431   let DecoderMethod = "DecodeSImm<4>";
434 def simm4s2 : Operand<i64>, ImmLeaf<i64,
435 [{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }]> {
436   let PrintMethod = "printImmScale<2>";
437   let ParserMatchClass = SImm4s2Operand;
438   let DecoderMethod = "DecodeSImm<4>";
441 def simm4s3 : Operand<i64>, ImmLeaf<i64,
442 [{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }]> {
443   let PrintMethod = "printImmScale<3>";
444   let ParserMatchClass = SImm4s3Operand;
445   let DecoderMethod = "DecodeSImm<4>";
448 def simm4s4 : Operand<i64>, ImmLeaf<i64,
449 [{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }]> {
450   let PrintMethod = "printImmScale<4>";
451   let ParserMatchClass = SImm4s4Operand;
452   let DecoderMethod = "DecodeSImm<4>";
454 def simm4s16 : Operand<i64>, ImmLeaf<i64,
455 [{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }]> {
456   let PrintMethod = "printImmScale<16>";
457   let ParserMatchClass = SImm4s16Operand;
458   let DecoderMethod = "DecodeSImm<4>";
461 def Imm1_8Operand : AsmImmRange<1, 8>;
462 def Imm1_16Operand : AsmImmRange<1, 16>;
463 def Imm1_32Operand : AsmImmRange<1, 32>;
464 def Imm1_64Operand : AsmImmRange<1, 64>;
466 class BranchTarget<int N> : AsmOperandClass {
467   let Name = "BranchTarget" # N;
468   let DiagnosticType = "InvalidLabel";
469   let PredicateMethod = "isBranchTarget<" # N # ">";
472 class PCRelLabel<int N> : BranchTarget<N> {
473   let Name = "PCRelLabel" # N;
476 def BranchTarget14Operand : BranchTarget<14>;
477 def BranchTarget26Operand : BranchTarget<26>;
478 def PCRelLabel19Operand   : PCRelLabel<19>;
480 def MovZSymbolG3AsmOperand : AsmOperandClass {
481   let Name = "MovZSymbolG3";
482   let RenderMethod = "addImmOperands";
485 def movz_symbol_g3 : Operand<i32> {
486   let ParserMatchClass = MovZSymbolG3AsmOperand;
489 def MovZSymbolG2AsmOperand : AsmOperandClass {
490   let Name = "MovZSymbolG2";
491   let RenderMethod = "addImmOperands";
494 def movz_symbol_g2 : Operand<i32> {
495   let ParserMatchClass = MovZSymbolG2AsmOperand;
498 def MovZSymbolG1AsmOperand : AsmOperandClass {
499   let Name = "MovZSymbolG1";
500   let RenderMethod = "addImmOperands";
503 def movz_symbol_g1 : Operand<i32> {
504   let ParserMatchClass = MovZSymbolG1AsmOperand;
507 def MovZSymbolG0AsmOperand : AsmOperandClass {
508   let Name = "MovZSymbolG0";
509   let RenderMethod = "addImmOperands";
512 def movz_symbol_g0 : Operand<i32> {
513   let ParserMatchClass = MovZSymbolG0AsmOperand;
516 def MovKSymbolG3AsmOperand : AsmOperandClass {
517   let Name = "MovKSymbolG3";
518   let RenderMethod = "addImmOperands";
521 def movk_symbol_g3 : Operand<i32> {
522   let ParserMatchClass = MovKSymbolG3AsmOperand;
525 def MovKSymbolG2AsmOperand : AsmOperandClass {
526   let Name = "MovKSymbolG2";
527   let RenderMethod = "addImmOperands";
530 def movk_symbol_g2 : Operand<i32> {
531   let ParserMatchClass = MovKSymbolG2AsmOperand;
534 def MovKSymbolG1AsmOperand : AsmOperandClass {
535   let Name = "MovKSymbolG1";
536   let RenderMethod = "addImmOperands";
539 def movk_symbol_g1 : Operand<i32> {
540   let ParserMatchClass = MovKSymbolG1AsmOperand;
543 def MovKSymbolG0AsmOperand : AsmOperandClass {
544   let Name = "MovKSymbolG0";
545   let RenderMethod = "addImmOperands";
548 def movk_symbol_g0 : Operand<i32> {
549   let ParserMatchClass = MovKSymbolG0AsmOperand;
552 class fixedpoint_i32<ValueType FloatVT>
553   : Operand<FloatVT>,
554     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
555   let EncoderMethod = "getFixedPointScaleOpValue";
556   let DecoderMethod = "DecodeFixedPointScaleImm32";
557   let ParserMatchClass = Imm1_32Operand;
560 class fixedpoint_i64<ValueType FloatVT>
561   : Operand<FloatVT>,
562     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
563   let EncoderMethod = "getFixedPointScaleOpValue";
564   let DecoderMethod = "DecodeFixedPointScaleImm64";
565   let ParserMatchClass = Imm1_64Operand;
568 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
569 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
570 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
572 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
573 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
574 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
576 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
577   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
578 }]> {
579   let EncoderMethod = "getVecShiftR8OpValue";
580   let DecoderMethod = "DecodeVecShiftR8Imm";
581   let ParserMatchClass = Imm1_8Operand;
583 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
584   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
585 }]> {
586   let EncoderMethod = "getVecShiftR16OpValue";
587   let DecoderMethod = "DecodeVecShiftR16Imm";
588   let ParserMatchClass = Imm1_16Operand;
590 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
591   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
592 }]> {
593   let EncoderMethod = "getVecShiftR16OpValue";
594   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
595   let ParserMatchClass = Imm1_8Operand;
597 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
598   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
599 }]> {
600   let EncoderMethod = "getVecShiftR32OpValue";
601   let DecoderMethod = "DecodeVecShiftR32Imm";
602   let ParserMatchClass = Imm1_32Operand;
604 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
605   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
606 }]> {
607   let EncoderMethod = "getVecShiftR32OpValue";
608   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
609   let ParserMatchClass = Imm1_16Operand;
611 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
612   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
613 }]> {
614   let EncoderMethod = "getVecShiftR64OpValue";
615   let DecoderMethod = "DecodeVecShiftR64Imm";
616   let ParserMatchClass = Imm1_64Operand;
618 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
619   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
620 }]> {
621   let EncoderMethod = "getVecShiftR64OpValue";
622   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
623   let ParserMatchClass = Imm1_32Operand;
626 def Imm0_1Operand : AsmImmRange<0, 1>;
627 def Imm0_7Operand : AsmImmRange<0, 7>;
628 def Imm0_15Operand : AsmImmRange<0, 15>;
629 def Imm0_31Operand : AsmImmRange<0, 31>;
630 def Imm0_63Operand : AsmImmRange<0, 63>;
632 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
633   return (((uint32_t)Imm) < 8);
634 }]> {
635   let EncoderMethod = "getVecShiftL8OpValue";
636   let DecoderMethod = "DecodeVecShiftL8Imm";
637   let ParserMatchClass = Imm0_7Operand;
639 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
640   return (((uint32_t)Imm) < 16);
641 }]> {
642   let EncoderMethod = "getVecShiftL16OpValue";
643   let DecoderMethod = "DecodeVecShiftL16Imm";
644   let ParserMatchClass = Imm0_15Operand;
646 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
647   return (((uint32_t)Imm) < 32);
648 }]> {
649   let EncoderMethod = "getVecShiftL32OpValue";
650   let DecoderMethod = "DecodeVecShiftL32Imm";
651   let ParserMatchClass = Imm0_31Operand;
653 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
654   return (((uint32_t)Imm) < 64);
655 }]> {
656   let EncoderMethod = "getVecShiftL64OpValue";
657   let DecoderMethod = "DecodeVecShiftL64Imm";
658   let ParserMatchClass = Imm0_63Operand;
662 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
663 // instructions for splatting repeating bit patterns across the immediate.
664 def logical_imm32_XFORM : SDNodeXForm<imm, [{
665   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
666   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
667 }]>;
668 def logical_imm64_XFORM : SDNodeXForm<imm, [{
669   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
670   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
671 }]>;
673 let DiagnosticType = "LogicalSecondSource" in {
674   def LogicalImm32Operand : AsmOperandClass {
675     let Name = "LogicalImm32";
676     let PredicateMethod = "isLogicalImm<int32_t>";
677     let RenderMethod = "addLogicalImmOperands<int32_t>";
678   }
679   def LogicalImm64Operand : AsmOperandClass {
680     let Name = "LogicalImm64";
681     let PredicateMethod = "isLogicalImm<int64_t>";
682     let RenderMethod = "addLogicalImmOperands<int64_t>";
683   }
684   def LogicalImm32NotOperand : AsmOperandClass {
685     let Name = "LogicalImm32Not";
686     let PredicateMethod = "isLogicalImm<int32_t>";
687     let RenderMethod = "addLogicalImmNotOperands<int32_t>";
688   }
689   def LogicalImm64NotOperand : AsmOperandClass {
690     let Name = "LogicalImm64Not";
691     let PredicateMethod = "isLogicalImm<int64_t>";
692     let RenderMethod = "addLogicalImmNotOperands<int64_t>";
693   }
695 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
696   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
697 }], logical_imm32_XFORM> {
698   let PrintMethod = "printLogicalImm<int32_t>";
699   let ParserMatchClass = LogicalImm32Operand;
701 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
702   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
703 }], logical_imm64_XFORM> {
704   let PrintMethod = "printLogicalImm<int64_t>";
705   let ParserMatchClass = LogicalImm64Operand;
707 def logical_imm32_not : Operand<i32> {
708   let ParserMatchClass = LogicalImm32NotOperand;
710 def logical_imm64_not : Operand<i64> {
711   let ParserMatchClass = LogicalImm64NotOperand;
714 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
715 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
716   return ((uint32_t)Imm) < 65536;
717 }]> {
718   let ParserMatchClass = AsmImmRange<0, 65535>;
719   let PrintMethod = "printImmHex";
722 // imm0_255 predicate - True if the immediate is in the range [0,255].
723 def Imm0_255Operand : AsmImmRange<0,255>;
725 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
726   return ((uint32_t)Imm) < 256;
727 }]> {
728   let ParserMatchClass = Imm0_255Operand;
729   let PrintMethod = "printImm";
732 // imm0_127 predicate - True if the immediate is in the range [0,127]
733 def Imm0_127Operand : AsmImmRange<0, 127>;
734 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
735   return ((uint32_t)Imm) < 128;
736 }]> {
737   let ParserMatchClass = Imm0_127Operand;
738   let PrintMethod = "printImm";
741 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
742 // for all shift-amounts.
744 // imm0_63 predicate - True if the immediate is in the range [0,63]
745 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
746   return ((uint64_t)Imm) < 64;
747 }]> {
748   let ParserMatchClass = Imm0_63Operand;
751 // imm0_31 predicate - True if the immediate is in the range [0,31]
752 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
753   return ((uint64_t)Imm) < 32;
754 }]> {
755   let ParserMatchClass = Imm0_31Operand;
758 // True if the 32-bit immediate is in the range [0,31]
759 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
760   return ((uint64_t)Imm) < 32;
761 }]> {
762   let ParserMatchClass = Imm0_31Operand;
765 // imm0_1 predicate - True if the immediate is in the range [0,1]
766 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
767   return ((uint64_t)Imm) < 2;
768 }]> {
769   let ParserMatchClass = Imm0_1Operand;
772 // imm0_15 predicate - True if the immediate is in the range [0,15]
773 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
774   return ((uint64_t)Imm) < 16;
775 }]> {
776   let ParserMatchClass = Imm0_15Operand;
779 // imm0_7 predicate - True if the immediate is in the range [0,7]
780 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
781   return ((uint64_t)Imm) < 8;
782 }]> {
783   let ParserMatchClass = Imm0_7Operand;
786 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
787 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
788   return ((uint32_t)Imm) < 16;
789 }]> {
790   let ParserMatchClass = Imm0_15Operand;
793 // An arithmetic shifter operand:
794 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
795 //  {5-0} - imm6
796 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
797   let PrintMethod = "printShifter";
798   let ParserMatchClass = !cast<AsmOperandClass>(
799                          "ArithmeticShifterOperand" # width);
802 def arith_shift32 : arith_shift<i32, 32>;
803 def arith_shift64 : arith_shift<i64, 64>;
805 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
806     : Operand<Ty>,
807       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
808   let PrintMethod = "printShiftedRegister";
809   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
812 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
813 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
815 // An arithmetic shifter operand:
816 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
817 //  {5-0} - imm6
818 class logical_shift<int width> : Operand<i32> {
819   let PrintMethod = "printShifter";
820   let ParserMatchClass = !cast<AsmOperandClass>(
821                          "LogicalShifterOperand" # width);
824 def logical_shift32 : logical_shift<32>;
825 def logical_shift64 : logical_shift<64>;
827 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
828     : Operand<Ty>,
829       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
830   let PrintMethod = "printShiftedRegister";
831   let MIOperandInfo = (ops regclass, shiftop);
834 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
835 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
837 // A logical vector shifter operand:
838 //  {7-6} - shift type: 00 = lsl
839 //  {5-0} - imm6: #0, #8, #16, or #24
840 def logical_vec_shift : Operand<i32> {
841   let PrintMethod = "printShifter";
842   let EncoderMethod = "getVecShifterOpValue";
843   let ParserMatchClass = LogicalVecShifterOperand;
846 // A logical vector half-word shifter operand:
847 //  {7-6} - shift type: 00 = lsl
848 //  {5-0} - imm6: #0 or #8
849 def logical_vec_hw_shift : Operand<i32> {
850   let PrintMethod = "printShifter";
851   let EncoderMethod = "getVecShifterOpValue";
852   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
855 // A vector move shifter operand:
856 //  {0} - imm1: #8 or #16
857 def move_vec_shift : Operand<i32> {
858   let PrintMethod = "printShifter";
859   let EncoderMethod = "getMoveVecShifterOpValue";
860   let ParserMatchClass = MoveVecShifterOperand;
863 let DiagnosticType = "AddSubSecondSource" in {
864   def AddSubImmOperand : AsmOperandClass {
865     let Name = "AddSubImm";
866     let ParserMethod = "tryParseImmWithOptionalShift";
867     let RenderMethod = "addImmWithOptionalShiftOperands<12>";
868   }
869   def AddSubImmNegOperand : AsmOperandClass {
870     let Name = "AddSubImmNeg";
871     let ParserMethod = "tryParseImmWithOptionalShift";
872     let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
873   }
875 // An ADD/SUB immediate shifter operand:
876 //  second operand:
877 //  {7-6} - shift type: 00 = lsl
878 //  {5-0} - imm6: #0 or #12
879 class addsub_shifted_imm<ValueType Ty>
880     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
881   let PrintMethod = "printAddSubImm";
882   let EncoderMethod = "getAddSubImmOpValue";
883   let ParserMatchClass = AddSubImmOperand;
884   let MIOperandInfo = (ops i32imm, i32imm);
887 class addsub_shifted_imm_neg<ValueType Ty>
888     : Operand<Ty> {
889   let EncoderMethod = "getAddSubImmOpValue";
890   let ParserMatchClass = AddSubImmNegOperand;
891   let MIOperandInfo = (ops i32imm, i32imm);
894 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
895 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
896 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
897 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
899 def gi_addsub_shifted_imm32 :
900     GIComplexOperandMatcher<s32, "selectArithImmed">,
901     GIComplexPatternEquiv<addsub_shifted_imm32>;
903 def gi_addsub_shifted_imm64 :
904     GIComplexOperandMatcher<s64, "selectArithImmed">,
905     GIComplexPatternEquiv<addsub_shifted_imm64>;
907 class neg_addsub_shifted_imm<ValueType Ty>
908     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
909   let PrintMethod = "printAddSubImm";
910   let EncoderMethod = "getAddSubImmOpValue";
911   let ParserMatchClass = AddSubImmOperand;
912   let MIOperandInfo = (ops i32imm, i32imm);
915 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
916 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
918 // An extend operand:
919 //  {5-3} - extend type
920 //  {2-0} - imm3
921 def arith_extend : Operand<i32> {
922   let PrintMethod = "printArithExtend";
923   let ParserMatchClass = ExtendOperand;
925 def arith_extend64 : Operand<i32> {
926   let PrintMethod = "printArithExtend";
927   let ParserMatchClass = ExtendOperand64;
930 // 'extend' that's a lsl of a 64-bit register.
931 def arith_extendlsl64 : Operand<i32> {
932   let PrintMethod = "printArithExtend";
933   let ParserMatchClass = ExtendOperandLSL64;
936 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
937                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
938   let PrintMethod = "printExtendedRegister";
939   let MIOperandInfo = (ops GPR32, arith_extend);
942 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
943                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
944   let PrintMethod = "printExtendedRegister";
945   let MIOperandInfo = (ops GPR32, arith_extend64);
948 // Floating-point immediate.
949 def fpimm16 : Operand<f16>,
950               FPImmLeaf<f16, [{
951       return AArch64_AM::getFP16Imm(Imm) != -1;
952     }], SDNodeXForm<fpimm, [{
953       APFloat InVal = N->getValueAPF();
954       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
955       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
956     }]>> {
957   let ParserMatchClass = FPImmOperand;
958   let PrintMethod = "printFPImmOperand";
960 def fpimm32 : Operand<f32>,
961               FPImmLeaf<f32, [{
962       return AArch64_AM::getFP32Imm(Imm) != -1;
963     }], SDNodeXForm<fpimm, [{
964       APFloat InVal = N->getValueAPF();
965       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
966       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
967     }]>> {
968   let ParserMatchClass = FPImmOperand;
969   let PrintMethod = "printFPImmOperand";
971 def fpimm64 : Operand<f64>,
972               FPImmLeaf<f64, [{
973       return AArch64_AM::getFP64Imm(Imm) != -1;
974     }], SDNodeXForm<fpimm, [{
975       APFloat InVal = N->getValueAPF();
976       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
977       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
978     }]>> {
979   let ParserMatchClass = FPImmOperand;
980   let PrintMethod = "printFPImmOperand";
983 def fpimm8 : Operand<i32> {
984   let ParserMatchClass = FPImmOperand;
985   let PrintMethod = "printFPImmOperand";
988 def fpimm0 : FPImmLeaf<fAny, [{
989   return Imm.isExactlyValue(+0.0);
990 }]>;
992 // Vector lane operands
993 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
994   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
995   let DiagnosticType = "Invalid" # Name;
996   let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
997   let RenderMethod = "addVectorIndexOperands";
1000 class AsmVectorIndexOpnd<AsmOperandClass mc, code pred>
1001     : Operand<i64>, ImmLeaf<i64, pred> {
1002   let ParserMatchClass = mc;
1003   let PrintMethod = "printVectorIndex";
1006 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1007 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1008 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1009 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1010 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1012 def VectorIndex1 : AsmVectorIndexOpnd<VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1013 def VectorIndexB : AsmVectorIndexOpnd<VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1014 def VectorIndexH : AsmVectorIndexOpnd<VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1015 def VectorIndexS : AsmVectorIndexOpnd<VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1016 def VectorIndexD : AsmVectorIndexOpnd<VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1018 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1019 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1020 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1021 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1022 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1024 def sve_elm_idx_extdup_b
1025   : AsmVectorIndexOpnd<SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1026 def sve_elm_idx_extdup_h
1027   : AsmVectorIndexOpnd<SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1028 def sve_elm_idx_extdup_s
1029   : AsmVectorIndexOpnd<SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1030 def sve_elm_idx_extdup_d
1031   : AsmVectorIndexOpnd<SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1032 def sve_elm_idx_extdup_q
1033   : AsmVectorIndexOpnd<SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1035 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1036 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1037 // are encoded as the eight bit value 'abcdefgh'.
1038 def simdimmtype10 : Operand<i32>,
1039                     FPImmLeaf<f64, [{
1040       return AArch64_AM::isAdvSIMDModImmType10(
1041                  Imm.bitcastToAPInt().getZExtValue());
1042     }], SDNodeXForm<fpimm, [{
1043       APFloat InVal = N->getValueAPF();
1044       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1045                                                            .bitcastToAPInt()
1046                                                            .getZExtValue());
1047       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1048     }]>> {
1049   let ParserMatchClass = SIMDImmType10Operand;
1050   let PrintMethod = "printSIMDType10Operand";
1054 //---
1055 // System management
1056 //---
1058 // Base encoding for system instruction operands.
1059 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1060 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1061                   list<dag> pattern = []>
1062     : I<oops, iops, asm, operands, "", pattern> {
1063   let Inst{31-22} = 0b1101010100;
1064   let Inst{21}    = L;
1067 // System instructions which do not have an Rt register.
1068 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1069                     list<dag> pattern = []>
1070     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1071   let Inst{4-0} = 0b11111;
1074 // System instructions which have an Rt register.
1075 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1076     : BaseSystemI<L, oops, iops, asm, operands>,
1077       Sched<[WriteSys]> {
1078   bits<5> Rt;
1079   let Inst{4-0} = Rt;
1082 // Hint instructions that take both a CRm and a 3-bit immediate.
1083 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1084 // model patterns with sufficiently fine granularity
1085 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1086   class HintI<string mnemonic>
1087       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1088                       [(int_aarch64_hint imm0_127:$imm)]>,
1089         Sched<[WriteHint]> {
1090     bits <7> imm;
1091     let Inst{20-12} = 0b000110010;
1092     let Inst{11-5} = imm;
1093   }
1095 // System instructions taking a single literal operand which encodes into
1096 // CRm. op2 differentiates the opcodes.
1097 def BarrierAsmOperand : AsmOperandClass {
1098   let Name = "Barrier";
1099   let ParserMethod = "tryParseBarrierOperand";
1101 def barrier_op : Operand<i32> {
1102   let PrintMethod = "printBarrierOption";
1103   let ParserMatchClass = BarrierAsmOperand;
1105 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1106                  list<dag> pattern = []>
1107     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1108       Sched<[WriteBarrier]> {
1109   bits<4> CRm;
1110   let Inst{20-12} = 0b000110011;
1111   let Inst{11-8} = CRm;
1112   let Inst{7-5} = opc;
1115 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1116     : SimpleSystemI<0, (ins), asm, "", pattern>,
1117       Sched<[]> {
1118   bits<4> CRm;
1119   let CRm = 0b0011;
1120   let Inst{31-12} = 0b11010101000000110010;
1121   let Inst{11-8} = CRm;
1122   let Inst{7-5} = op2;
1123   let Inst{4-0} = 0b11111;
1126 // MRS/MSR system instructions. These have different operand classes because
1127 // a different subset of registers can be accessed through each instruction.
1128 def MRSSystemRegisterOperand : AsmOperandClass {
1129   let Name = "MRSSystemRegister";
1130   let ParserMethod = "tryParseSysReg";
1131   let DiagnosticType = "MRS";
1133 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1134 def mrs_sysreg_op : Operand<i32> {
1135   let ParserMatchClass = MRSSystemRegisterOperand;
1136   let DecoderMethod = "DecodeMRSSystemRegister";
1137   let PrintMethod = "printMRSSystemRegister";
1140 def MSRSystemRegisterOperand : AsmOperandClass {
1141   let Name = "MSRSystemRegister";
1142   let ParserMethod = "tryParseSysReg";
1143   let DiagnosticType = "MSR";
1145 def msr_sysreg_op : Operand<i32> {
1146   let ParserMatchClass = MSRSystemRegisterOperand;
1147   let DecoderMethod = "DecodeMSRSystemRegister";
1148   let PrintMethod = "printMSRSystemRegister";
1151 def PSBHintOperand : AsmOperandClass {
1152   let Name = "PSBHint";
1153   let ParserMethod = "tryParsePSBHint";
1155 def psbhint_op : Operand<i32> {
1156   let ParserMatchClass = PSBHintOperand;
1157   let PrintMethod = "printPSBHintOp";
1158   let MCOperandPredicate = [{
1159     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1160     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1161     if (!MCOp.isImm())
1162       return false;
1163     return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1164   }];
1167 def BTIHintOperand : AsmOperandClass {
1168   let Name = "BTIHint";
1169   let ParserMethod = "tryParseBTIHint";
1171 def btihint_op : Operand<i32> {
1172   let ParserMatchClass = BTIHintOperand;
1173   let PrintMethod = "printBTIHintOp";
1174   let MCOperandPredicate = [{
1175     // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1176     if (!MCOp.isImm())
1177       return false;
1178     return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1179   }];
1182 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1183                        "mrs", "\t$Rt, $systemreg"> {
1184   bits<16> systemreg;
1185   let Inst{20-5} = systemreg;
1188 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1189 // Explicitly modeling each of the system register as a register class
1190 // would do it, but feels like overkill at this point.
1191 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1192                        "msr", "\t$systemreg, $Rt"> {
1193   bits<16> systemreg;
1194   let Inst{20-5} = systemreg;
1197 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1198   let Name = "SystemPStateFieldWithImm0_15";
1199   let ParserMethod = "tryParseSysReg";
1201 def pstatefield4_op : Operand<i32> {
1202   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1203   let PrintMethod = "printSystemPStateField";
1206 // Instructions to modify PSTATE, no input reg
1207 let Defs = [NZCV] in
1208 class PstateWriteSimple<dag iops, string asm, string operands>
1209   : SimpleSystemI<0, iops, asm, operands> {
1211   let Inst{20-19} = 0b00;
1212   let Inst{15-12} = 0b0100;
1215 class MSRpstateImm0_15
1216   : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1217                   "\t$pstatefield, $imm">,
1218     Sched<[WriteSys]> {
1220   bits<6> pstatefield;
1221   bits<4> imm;
1222   let Inst{18-16} = pstatefield{5-3};
1223   let Inst{11-8} = imm;
1224   let Inst{7-5} = pstatefield{2-0};
1226   let DecoderMethod = "DecodeSystemPStateInstruction";
1227   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1228   // Fail the decoder should attempt to decode the instruction as MSRI.
1229   let hasCompleteDecoder = 0;
1232 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1233   let Name = "SystemPStateFieldWithImm0_1";
1234   let ParserMethod = "tryParseSysReg";
1236 def pstatefield1_op : Operand<i32> {
1237   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1238   let PrintMethod = "printSystemPStateField";
1241 class MSRpstateImm0_1
1242   : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1243                  "\t$pstatefield, $imm">,
1244     Sched<[WriteSys]> {
1246   bits<6> pstatefield;
1247   bit imm;
1248   let Inst{18-16} = pstatefield{5-3};
1249   let Inst{11-9} = 0b000;
1250   let Inst{8} = imm;
1251   let Inst{7-5} = pstatefield{2-0};
1253   let DecoderMethod = "DecodeSystemPStateInstruction";
1254   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1255   // Fail the decoder should attempt to decode the instruction as MSRI.
1256   let hasCompleteDecoder = 0;
1259 // SYS and SYSL generic system instructions.
1260 def SysCRAsmOperand : AsmOperandClass {
1261   let Name = "SysCR";
1262   let ParserMethod = "tryParseSysCROperand";
1265 def sys_cr_op : Operand<i32> {
1266   let PrintMethod = "printSysCROperand";
1267   let ParserMatchClass = SysCRAsmOperand;
1270 class SystemXtI<bit L, string asm>
1271   : RtSystemI<L, (outs),
1272        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1273        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1274   bits<3> op1;
1275   bits<4> Cn;
1276   bits<4> Cm;
1277   bits<3> op2;
1278   let Inst{20-19} = 0b01;
1279   let Inst{18-16} = op1;
1280   let Inst{15-12} = Cn;
1281   let Inst{11-8}  = Cm;
1282   let Inst{7-5}   = op2;
1285 class SystemLXtI<bit L, string asm>
1286   : RtSystemI<L, (outs),
1287        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1288        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1289   bits<3> op1;
1290   bits<4> Cn;
1291   bits<4> Cm;
1292   bits<3> op2;
1293   let Inst{20-19} = 0b01;
1294   let Inst{18-16} = op1;
1295   let Inst{15-12} = Cn;
1296   let Inst{11-8}  = Cm;
1297   let Inst{7-5}   = op2;
1301 // Branch (register) instructions:
1303 //  case opc of
1304 //    0001 blr
1305 //    0000 br
1306 //    0101 dret
1307 //    0100 eret
1308 //    0010 ret
1309 //    otherwise UNDEFINED
1310 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1311                     string operands, list<dag> pattern>
1312     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1313   let Inst{31-25} = 0b1101011;
1314   let Inst{24-21} = opc;
1315   let Inst{20-16} = 0b11111;
1316   let Inst{15-10} = 0b000000;
1317   let Inst{4-0}   = 0b00000;
1320 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1321     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1322   bits<5> Rn;
1323   let Inst{9-5} = Rn;
1326 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1327 class SpecialReturn<bits<4> opc, string asm>
1328     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1329   let Inst{9-5} = 0b11111;
1332 let mayLoad = 1 in
1333 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1334   : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1335   Sched<[]> {
1336   bits<5> Rn;
1337   bits<5> Rt;
1338   let Inst{31-30} = sz;
1339   let Inst{29-10} = 0b11100010111111110000;
1340   let Inst{9-5} = Rn;
1341   let Inst{4-0} = Rt;
1344 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1345                list<dag> pattern>
1346   : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1347   let Inst{31-25} = 0b1101011;
1348   let Inst{20-11} = 0b1111100001;
1349   let Inst{10} = M;
1350   let Inst{4-0} = 0b11111;
1353 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1354   : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1355   bits<5> Rn;
1356   bits<5> Rm;
1357   let Inst{24-22} = 0b100;
1358   let Inst{21} = op;
1359   let Inst{9-5} = Rn;
1360   let Inst{4-0} = Rm;
1363 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1364   : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1365   bits<5> Rn;
1366   let Inst{24} = 0;
1367   let Inst{23-21} = opc;
1368   let Inst{9-5} = Rn;
1371 class AuthReturn<bits<3> op, bits<1> M, string asm>
1372   : AuthBase<M, (outs), (ins), asm, "", []> {
1373   let Inst{24} = 0;
1374   let Inst{23-21} = op;
1375   let Inst{9-0} = 0b1111111111;
1378 let mayLoad = 1 in
1379 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1380                    string operands, string cstr, Operand opr>
1381   : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1382   bits<10> offset;
1383   bits<5> Rn;
1384   bits<5> Rt;
1385   let Inst{31-24} = 0b11111000;
1386   let Inst{23} = M;
1387   let Inst{22} = offset{9};
1388   let Inst{21} = 1;
1389   let Inst{20-12} = offset{8-0};
1390   let Inst{11} = W;
1391   let Inst{10} = 1;
1392   let Inst{9-5} = Rn;
1393   let Inst{4-0} = Rt;
1396 multiclass AuthLoad<bit M, string asm, Operand opr> {
1397   def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1398                                (ins GPR64sp:$Rn, opr:$offset),
1399                                asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1400   def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1401                                (ins GPR64sp:$Rn, opr:$offset),
1402                                asm, "\t$Rt, [$Rn, $offset]!",
1403                                "$Rn = $wback,@earlyclobber $wback", opr>;
1405   def : InstAlias<asm # "\t$Rt, [$Rn]",
1406                   (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1409 //---
1410 // Conditional branch instruction.
1411 //---
1413 // Condition code.
1414 // 4-bit immediate. Pretty-printed as <cc>
1415 def ccode : Operand<i32> {
1416   let PrintMethod = "printCondCode";
1417   let ParserMatchClass = CondCode;
1419 def inv_ccode : Operand<i32> {
1420   // AL and NV are invalid in the aliases which use inv_ccode
1421   let PrintMethod = "printInverseCondCode";
1422   let ParserMatchClass = CondCode;
1423   let MCOperandPredicate = [{
1424     return MCOp.isImm() &&
1425            MCOp.getImm() != AArch64CC::AL &&
1426            MCOp.getImm() != AArch64CC::NV;
1427   }];
1430 // Conditional branch target. 19-bit immediate. The low two bits of the target
1431 // offset are implied zero and so are not part of the immediate.
1432 def am_brcond : Operand<OtherVT> {
1433   let EncoderMethod = "getCondBranchTargetOpValue";
1434   let DecoderMethod = "DecodePCRelLabel19";
1435   let PrintMethod = "printAlignedLabel";
1436   let ParserMatchClass = PCRelLabel19Operand;
1437   let OperandType = "OPERAND_PCREL";
1440 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1441                      "b", ".$cond\t$target", "",
1442                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1443                    Sched<[WriteBr]> {
1444   let isBranch = 1;
1445   let isTerminator = 1;
1446   let Uses = [NZCV];
1448   bits<4> cond;
1449   bits<19> target;
1450   let Inst{31-24} = 0b01010100;
1451   let Inst{23-5} = target;
1452   let Inst{4} = 0;
1453   let Inst{3-0} = cond;
1456 //---
1457 // Compare-and-branch instructions.
1458 //---
1459 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1460     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1461          asm, "\t$Rt, $target", "",
1462          [(node regtype:$Rt, bb:$target)]>,
1463       Sched<[WriteBr]> {
1464   let isBranch = 1;
1465   let isTerminator = 1;
1467   bits<5> Rt;
1468   bits<19> target;
1469   let Inst{30-25} = 0b011010;
1470   let Inst{24}    = op;
1471   let Inst{23-5}  = target;
1472   let Inst{4-0}   = Rt;
1475 multiclass CmpBranch<bit op, string asm, SDNode node> {
1476   def W : BaseCmpBranch<GPR32, op, asm, node> {
1477     let Inst{31} = 0;
1478   }
1479   def X : BaseCmpBranch<GPR64, op, asm, node> {
1480     let Inst{31} = 1;
1481   }
1484 //---
1485 // Test-bit-and-branch instructions.
1486 //---
1487 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1488 // the target offset are implied zero and so are not part of the immediate.
1489 def am_tbrcond : Operand<OtherVT> {
1490   let EncoderMethod = "getTestBranchTargetOpValue";
1491   let PrintMethod = "printAlignedLabel";
1492   let ParserMatchClass = BranchTarget14Operand;
1493   let OperandType = "OPERAND_PCREL";
1496 // AsmOperand classes to emit (or not) special diagnostics
1497 def TBZImm0_31Operand : AsmOperandClass {
1498   let Name = "TBZImm0_31";
1499   let PredicateMethod = "isImmInRange<0,31>";
1500   let RenderMethod = "addImmOperands";
1502 def TBZImm32_63Operand : AsmOperandClass {
1503   let Name = "Imm32_63";
1504   let PredicateMethod = "isImmInRange<32,63>";
1505   let DiagnosticType = "InvalidImm0_63";
1506   let RenderMethod = "addImmOperands";
1509 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1510   return (((uint32_t)Imm) < 32);
1511 }]> {
1512   let ParserMatchClass = matcher;
1515 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1516 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1518 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1519   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1520 }]> {
1521   let ParserMatchClass = TBZImm32_63Operand;
1524 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1525                      bit op, string asm, SDNode node>
1526     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1527        asm, "\t$Rt, $bit_off, $target", "",
1528        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1529       Sched<[WriteBr]> {
1530   let isBranch = 1;
1531   let isTerminator = 1;
1533   bits<5> Rt;
1534   bits<6> bit_off;
1535   bits<14> target;
1537   let Inst{30-25} = 0b011011;
1538   let Inst{24}    = op;
1539   let Inst{23-19} = bit_off{4-0};
1540   let Inst{18-5}  = target;
1541   let Inst{4-0}   = Rt;
1543   let DecoderMethod = "DecodeTestAndBranch";
1546 multiclass TestBranch<bit op, string asm, SDNode node> {
1547   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1548     let Inst{31} = 0;
1549   }
1551   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1552     let Inst{31} = 1;
1553   }
1555   // Alias X-reg with 0-31 imm to W-Reg.
1556   def : InstAlias<asm # "\t$Rd, $imm, $target",
1557                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1558                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1559   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1560             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1561             tbz_imm0_31_diag:$imm, bb:$target)>;
1564 //---
1565 // Unconditional branch (immediate) instructions.
1566 //---
1567 def am_b_target : Operand<OtherVT> {
1568   let EncoderMethod = "getBranchTargetOpValue";
1569   let PrintMethod = "printAlignedLabel";
1570   let ParserMatchClass = BranchTarget26Operand;
1571   let OperandType = "OPERAND_PCREL";
1573 def am_bl_target : Operand<i64> {
1574   let EncoderMethod = "getBranchTargetOpValue";
1575   let PrintMethod = "printAlignedLabel";
1576   let ParserMatchClass = BranchTarget26Operand;
1577   let OperandType = "OPERAND_PCREL";
1580 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1581     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1582   bits<26> addr;
1583   let Inst{31}    = op;
1584   let Inst{30-26} = 0b00101;
1585   let Inst{25-0}  = addr;
1587   let DecoderMethod = "DecodeUnconditionalBranch";
1590 class BranchImm<bit op, string asm, list<dag> pattern>
1591     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1592 class CallImm<bit op, string asm, list<dag> pattern>
1593     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1595 //---
1596 // Basic one-operand data processing instructions.
1597 //---
1599 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1600 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1601                          SDPatternOperator node>
1602   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1603       [(set regtype:$Rd, (node regtype:$Rn))]>,
1604     Sched<[WriteI, ReadI]> {
1605   bits<5> Rd;
1606   bits<5> Rn;
1608   let Inst{30-13} = 0b101101011000000000;
1609   let Inst{12-10} = opc;
1610   let Inst{9-5}   = Rn;
1611   let Inst{4-0}   = Rd;
1614 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1615 multiclass OneOperandData<bits<3> opc, string asm,
1616                           SDPatternOperator node = null_frag> {
1617   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1618     let Inst{31} = 0;
1619   }
1621   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1622     let Inst{31} = 1;
1623   }
1626 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1627     : BaseOneOperandData<opc, GPR32, asm, node> {
1628   let Inst{31} = 0;
1631 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1632     : BaseOneOperandData<opc, GPR64, asm, node> {
1633   let Inst{31} = 1;
1636 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1637   : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1638       []>,
1639     Sched<[WriteI, ReadI]> {
1640   bits<5> Rd;
1641   bits<5> Rn;
1642   let Inst{31-15} = 0b11011010110000010;
1643   let Inst{14-12} = opcode_prefix;
1644   let Inst{11-10} = opcode;
1645   let Inst{9-5} = Rn;
1646   let Inst{4-0} = Rd;
1649 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1650   : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1651   bits<5> Rd;
1652   let Inst{31-15} = 0b11011010110000010;
1653   let Inst{14-12} = opcode_prefix;
1654   let Inst{11-10} = opcode;
1655   let Inst{9-5} = 0b11111;
1656   let Inst{4-0} = Rd;
1659 class SignAuthTwoOperand<bits<4> opc, string asm,
1660                          SDPatternOperator OpNode>
1661   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1662       asm, "\t$Rd, $Rn, $Rm", "",
1663       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1664     Sched<[WriteI, ReadI, ReadI]> {
1665   bits<5> Rd;
1666   bits<5> Rn;
1667   bits<5> Rm;
1668   let Inst{31-21} = 0b10011010110;
1669   let Inst{20-16} = Rm;
1670   let Inst{15-14} = 0b00;
1671   let Inst{13-10} = opc;
1672   let Inst{9-5}   = Rn;
1673   let Inst{4-0}   = Rd;
1676 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1677 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1678     : I<(outs), iops, asm, ops, "", []>,
1679       Sched<[WriteI, ReadI, ReadI]> {
1680   let Uses = [NZCV];
1681   bits<5> Rn;
1682   let Inst{31}    = sf;
1683   let Inst{30-15} = 0b0111010000000000;
1684   let Inst{14}    = sz;
1685   let Inst{13-10} = 0b0010;
1686   let Inst{9-5}   = Rn;
1687   let Inst{4-0}   = 0b01101;
1690 class FlagRotate<dag iops, string asm, string ops>
1691     : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1692   bits<6> imm;
1693   bits<4> mask;
1694   let Inst{20-15} = imm;
1695   let Inst{13-10} = 0b0001;
1696   let Inst{4}     = 0b0;
1697   let Inst{3-0}   = mask;
1700 //---
1701 // Basic two-operand data processing instructions.
1702 //---
1703 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1704                           list<dag> pattern>
1705     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1706         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1707       Sched<[WriteI, ReadI, ReadI]> {
1708   let Uses = [NZCV];
1709   bits<5> Rd;
1710   bits<5> Rn;
1711   bits<5> Rm;
1712   let Inst{30}    = isSub;
1713   let Inst{28-21} = 0b11010000;
1714   let Inst{20-16} = Rm;
1715   let Inst{15-10} = 0;
1716   let Inst{9-5}   = Rn;
1717   let Inst{4-0}   = Rd;
1720 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1721                       SDNode OpNode>
1722     : BaseBaseAddSubCarry<isSub, regtype, asm,
1723         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1725 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1726                               SDNode OpNode>
1727     : BaseBaseAddSubCarry<isSub, regtype, asm,
1728         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1729          (implicit NZCV)]> {
1730   let Defs = [NZCV];
1733 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1734                        SDNode OpNode, SDNode OpNode_setflags> {
1735   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1736     let Inst{31} = 0;
1737     let Inst{29} = 0;
1738   }
1739   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1740     let Inst{31} = 1;
1741     let Inst{29} = 0;
1742   }
1744   // Sets flags.
1745   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1746                                     OpNode_setflags> {
1747     let Inst{31} = 0;
1748     let Inst{29} = 1;
1749   }
1750   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1751                                     OpNode_setflags> {
1752     let Inst{31} = 1;
1753     let Inst{29} = 1;
1754   }
1757 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1758                      SDPatternOperator OpNode,
1759                      RegisterClass in1regtype = regtype,
1760                      RegisterClass in2regtype = regtype>
1761   : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
1762       asm, "\t$Rd, $Rn, $Rm", "",
1763       [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
1764   bits<5> Rd;
1765   bits<5> Rn;
1766   bits<5> Rm;
1767   let Inst{30-21} = 0b0011010110;
1768   let Inst{20-16} = Rm;
1769   let Inst{15-14} = 0b00;
1770   let Inst{13-10} = opc;
1771   let Inst{9-5}   = Rn;
1772   let Inst{4-0}   = Rd;
1775 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1776               SDPatternOperator OpNode>
1777     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1778   let Inst{10}    = isSigned;
1781 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1782   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1783            Sched<[WriteID32, ReadID, ReadID]> {
1784     let Inst{31} = 0;
1785   }
1786   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1787            Sched<[WriteID64, ReadID, ReadID]> {
1788     let Inst{31} = 1;
1789   }
1792 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1793                 SDPatternOperator OpNode = null_frag>
1794   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1795     Sched<[WriteIS, ReadI]> {
1796   let Inst{11-10} = shift_type;
1799 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1800   def Wr : BaseShift<shift_type, GPR32, asm> {
1801     let Inst{31} = 0;
1802   }
1804   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1805     let Inst{31} = 1;
1806   }
1808   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1809             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1810                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1812   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1813             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1815   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1816             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1818   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1819             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1821   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
1822             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1823                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1825   def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
1826             (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1827                 (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1830 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1831     : InstAlias<asm#"\t$dst, $src1, $src2",
1832                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1834 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1835                        RegisterClass addtype, string asm,
1836                        list<dag> pattern>
1837   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1838       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1839   bits<5> Rd;
1840   bits<5> Rn;
1841   bits<5> Rm;
1842   bits<5> Ra;
1843   let Inst{30-24} = 0b0011011;
1844   let Inst{23-21} = opc;
1845   let Inst{20-16} = Rm;
1846   let Inst{15}    = isSub;
1847   let Inst{14-10} = Ra;
1848   let Inst{9-5}   = Rn;
1849   let Inst{4-0}   = Rd;
1852 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1853   // MADD/MSUB generation is decided by MachineCombiner.cpp
1854   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1855       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1856       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1857     let Inst{31} = 0;
1858   }
1860   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1861       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1862       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1863     let Inst{31} = 1;
1864   }
1867 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1868                    SDNode AccNode, SDNode ExtNode>
1869   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1870     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1871                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1872     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1873   let Inst{31} = 1;
1876 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1877   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1878       asm, "\t$Rd, $Rn, $Rm", "",
1879       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1880     Sched<[WriteIM64, ReadIM, ReadIM]> {
1881   bits<5> Rd;
1882   bits<5> Rn;
1883   bits<5> Rm;
1884   let Inst{31-24} = 0b10011011;
1885   let Inst{23-21} = opc;
1886   let Inst{20-16} = Rm;
1887   let Inst{15}    = 0;
1888   let Inst{9-5}   = Rn;
1889   let Inst{4-0}   = Rd;
1891   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1892   // (i.e. all bits 1) but is ignored by the processor.
1893   let PostEncoderMethod = "fixMulHigh";
1896 class MulAccumWAlias<string asm, Instruction inst>
1897     : InstAlias<asm#"\t$dst, $src1, $src2",
1898                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1899 class MulAccumXAlias<string asm, Instruction inst>
1900     : InstAlias<asm#"\t$dst, $src1, $src2",
1901                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1902 class WideMulAccumAlias<string asm, Instruction inst>
1903     : InstAlias<asm#"\t$dst, $src1, $src2",
1904                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1906 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1907               SDPatternOperator OpNode, string asm>
1908   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1909       asm, "\t$Rd, $Rn, $Rm", "",
1910       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1911     Sched<[WriteISReg, ReadI, ReadISReg]> {
1912   bits<5> Rd;
1913   bits<5> Rn;
1914   bits<5> Rm;
1916   let Inst{31} = sf;
1917   let Inst{30-21} = 0b0011010110;
1918   let Inst{20-16} = Rm;
1919   let Inst{15-13} = 0b010;
1920   let Inst{12} = C;
1921   let Inst{11-10} = sz;
1922   let Inst{9-5} = Rn;
1923   let Inst{4-0} = Rd;
1924   let Predicates = [HasCRC];
1927 //---
1928 // Address generation.
1929 //---
1931 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1932     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1933         pattern>,
1934       Sched<[WriteI]> {
1935   bits<5>  Xd;
1936   bits<21> label;
1937   let Inst{31}    = page;
1938   let Inst{30-29} = label{1-0};
1939   let Inst{28-24} = 0b10000;
1940   let Inst{23-5}  = label{20-2};
1941   let Inst{4-0}   = Xd;
1943   let DecoderMethod = "DecodeAdrInstruction";
1946 //---
1947 // Move immediate.
1948 //---
1950 def movimm32_imm : Operand<i32> {
1951   let ParserMatchClass = AsmImmRange<0, 65535>;
1952   let EncoderMethod = "getMoveWideImmOpValue";
1953   let PrintMethod = "printImm";
1955 def movimm32_shift : Operand<i32> {
1956   let PrintMethod = "printShifter";
1957   let ParserMatchClass = MovImm32ShifterOperand;
1959 def movimm64_shift : Operand<i32> {
1960   let PrintMethod = "printShifter";
1961   let ParserMatchClass = MovImm64ShifterOperand;
1964 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1965 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1966                         string asm>
1967   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1968        asm, "\t$Rd, $imm$shift", "", []>,
1969     Sched<[WriteImm]> {
1970   bits<5> Rd;
1971   bits<16> imm;
1972   bits<6> shift;
1973   let Inst{30-29} = opc;
1974   let Inst{28-23} = 0b100101;
1975   let Inst{22-21} = shift{5-4};
1976   let Inst{20-5}  = imm;
1977   let Inst{4-0}   = Rd;
1979   let DecoderMethod = "DecodeMoveImmInstruction";
1982 multiclass MoveImmediate<bits<2> opc, string asm> {
1983   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1984     let Inst{31} = 0;
1985   }
1987   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1988     let Inst{31} = 1;
1989   }
1992 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1993 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1994                           string asm>
1995   : I<(outs regtype:$Rd),
1996       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1997        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1998     Sched<[WriteI, ReadI]> {
1999   bits<5> Rd;
2000   bits<16> imm;
2001   bits<6> shift;
2002   let Inst{30-29} = opc;
2003   let Inst{28-23} = 0b100101;
2004   let Inst{22-21} = shift{5-4};
2005   let Inst{20-5}  = imm;
2006   let Inst{4-0}   = Rd;
2008   let DecoderMethod = "DecodeMoveImmInstruction";
2011 multiclass InsertImmediate<bits<2> opc, string asm> {
2012   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2013     let Inst{31} = 0;
2014   }
2016   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2017     let Inst{31} = 1;
2018   }
2021 //---
2022 // Add/Subtract
2023 //---
2025 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2026                     string asm_inst, string asm_ops,
2027                     dag inputs, dag pattern>
2028     : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2029       Sched<[WriteI, ReadI]> {
2030   bits<5>  Rd;
2031   bits<5>  Rn;
2032   let Inst{30}    = isSub;
2033   let Inst{29}    = setFlags;
2034   let Inst{28-24} = 0b10001;
2035   let Inst{9-5}   = Rn;
2036   let Inst{4-0}   = Rd;
2039 class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2040                      RegisterClass srcRegtype, addsub_shifted_imm immtype,
2041                      string asm_inst, SDPatternOperator OpNode>
2042     : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2043                     (ins srcRegtype:$Rn, immtype:$imm),
2044                     (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2045   bits<14> imm;
2046   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2047   let Inst{21-10} = imm{11-0};
2048   let DecoderMethod = "DecodeAddSubImmShift";
2051 class BaseAddSubRegPseudo<RegisterClass regtype,
2052                           SDPatternOperator OpNode>
2053     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2054              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2055       Sched<[WriteI, ReadI, ReadI]>;
2057 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2058                      arith_shifted_reg shifted_regtype, string asm,
2059                      SDPatternOperator OpNode>
2060     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2061         asm, "\t$Rd, $Rn, $Rm", "",
2062         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2063       Sched<[WriteISReg, ReadI, ReadISReg]> {
2064   // The operands are in order to match the 'addr' MI operands, so we
2065   // don't need an encoder method and by-name matching. Just use the default
2066   // in-order handling. Since we're using by-order, make sure the names
2067   // do not match.
2068   bits<5> dst;
2069   bits<5> src1;
2070   bits<5> src2;
2071   bits<8> shift;
2072   let Inst{30}    = isSub;
2073   let Inst{29}    = setFlags;
2074   let Inst{28-24} = 0b01011;
2075   let Inst{23-22} = shift{7-6};
2076   let Inst{21}    = 0;
2077   let Inst{20-16} = src2;
2078   let Inst{15-10} = shift{5-0};
2079   let Inst{9-5}   = src1;
2080   let Inst{4-0}   = dst;
2082   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2085 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2086                      RegisterClass src1Regtype, Operand src2Regtype,
2087                      string asm, SDPatternOperator OpNode>
2088     : I<(outs dstRegtype:$R1),
2089         (ins src1Regtype:$R2, src2Regtype:$R3),
2090         asm, "\t$R1, $R2, $R3", "",
2091         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2092       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2093   bits<5> Rd;
2094   bits<5> Rn;
2095   bits<5> Rm;
2096   bits<6> ext;
2097   let Inst{30}    = isSub;
2098   let Inst{29}    = setFlags;
2099   let Inst{28-24} = 0b01011;
2100   let Inst{23-21} = 0b001;
2101   let Inst{20-16} = Rm;
2102   let Inst{15-13} = ext{5-3};
2103   let Inst{12-10} = ext{2-0};
2104   let Inst{9-5}   = Rn;
2105   let Inst{4-0}   = Rd;
2107   let DecoderMethod = "DecodeAddSubERegInstruction";
2110 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2111 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2112                        RegisterClass src1Regtype, RegisterClass src2Regtype,
2113                        Operand ext_op, string asm>
2114     : I<(outs dstRegtype:$Rd),
2115         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2116         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2117       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2118   bits<5> Rd;
2119   bits<5> Rn;
2120   bits<5> Rm;
2121   bits<6> ext;
2122   let Inst{30}    = isSub;
2123   let Inst{29}    = setFlags;
2124   let Inst{28-24} = 0b01011;
2125   let Inst{23-21} = 0b001;
2126   let Inst{20-16} = Rm;
2127   let Inst{15}    = ext{5};
2128   let Inst{12-10} = ext{2-0};
2129   let Inst{9-5}   = Rn;
2130   let Inst{4-0}   = Rd;
2132   let DecoderMethod = "DecodeAddSubERegInstruction";
2135 // Aliases for register+register add/subtract.
2136 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2137                      RegisterClass src1Regtype, RegisterClass src2Regtype,
2138                      int shiftExt>
2139     : InstAlias<asm#"\t$dst, $src1, $src2",
2140                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2141                       shiftExt)>;
2143 multiclass AddSub<bit isSub, string mnemonic, string alias,
2144                   SDPatternOperator OpNode = null_frag> {
2145   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2146   // Add/Subtract immediate
2147   // Increase the weight of the immediate variant to try to match it before
2148   // the extended register variant.
2149   // We used to match the register variant before the immediate when the
2150   // register argument could be implicitly zero-extended.
2151   let AddedComplexity = 6 in
2152   def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2153                            mnemonic, OpNode> {
2154     let Inst{31} = 0;
2155   }
2156   let AddedComplexity = 6 in
2157   def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2158                            mnemonic, OpNode> {
2159     let Inst{31} = 1;
2160   }
2162   // Add/Subtract register - Only used for CodeGen
2163   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2164   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2166   // Add/Subtract shifted register
2167   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2168                            OpNode> {
2169     let Inst{31} = 0;
2170   }
2171   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2172                            OpNode> {
2173     let Inst{31} = 1;
2174   }
2175   }
2177   // Add/Subtract extended register
2178   let AddedComplexity = 1, hasSideEffects = 0 in {
2179   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2180                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2181     let Inst{31} = 0;
2182   }
2183   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2184                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
2185     let Inst{31} = 1;
2186   }
2187   }
2189   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2190                                arith_extendlsl64, mnemonic> {
2191     // UXTX and SXTX only.
2192     let Inst{14-13} = 0b11;
2193     let Inst{31} = 1;
2194   }
2196   // add Rd, Rb, -imm -> sub Rd, Rn, imm
2197   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2198                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2199                       addsub_shifted_imm32_neg:$imm), 0>;
2200   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2201                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2202                        addsub_shifted_imm64_neg:$imm), 0>;
2204   // Register/register aliases with no shift when SP is not used.
2205   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2206                        GPR32, GPR32, GPR32, 0>;
2207   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2208                        GPR64, GPR64, GPR64, 0>;
2210   // Register/register aliases with no shift when either the destination or
2211   // first source register is SP.
2212   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2213                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2214   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2215                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2216   def : AddSubRegAlias<mnemonic,
2217                        !cast<Instruction>(NAME#"Xrx64"),
2218                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2219   def : AddSubRegAlias<mnemonic,
2220                        !cast<Instruction>(NAME#"Xrx64"),
2221                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2224 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2225                    string alias, string cmpAlias> {
2226   let isCompare = 1, Defs = [NZCV] in {
2227   // Add/Subtract immediate
2228   def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2229                            mnemonic, OpNode> {
2230     let Inst{31} = 0;
2231   }
2232   def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2233                            mnemonic, OpNode> {
2234     let Inst{31} = 1;
2235   }
2237   // Add/Subtract register
2238   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2239   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2241   // Add/Subtract shifted register
2242   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2243                            OpNode> {
2244     let Inst{31} = 0;
2245   }
2246   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2247                            OpNode> {
2248     let Inst{31} = 1;
2249   }
2251   // Add/Subtract extended register
2252   let AddedComplexity = 1 in {
2253   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2254                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2255     let Inst{31} = 0;
2256   }
2257   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2258                            arith_extended_reg32<i64>, mnemonic, OpNode> {
2259     let Inst{31} = 1;
2260   }
2261   }
2263   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2264                                arith_extendlsl64, mnemonic> {
2265     // UXTX and SXTX only.
2266     let Inst{14-13} = 0b11;
2267     let Inst{31} = 1;
2268   }
2269   } // Defs = [NZCV]
2271   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2272   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2273                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2274                       addsub_shifted_imm32_neg:$imm), 0>;
2275   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2276                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2277                        addsub_shifted_imm64_neg:$imm), 0>;
2279   // Compare aliases
2280   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2281                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2282   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2283                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2284   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2285                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2286   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2287                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2288   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2289                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2290   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2291                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2292   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2293                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2295   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2296   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2297                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2298   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2299                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2301   // Compare shorthands
2302   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2303                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2304   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2305                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2306   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2307                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2308   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2309                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2311   // Register/register aliases with no shift when SP is not used.
2312   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2313                        GPR32, GPR32, GPR32, 0>;
2314   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2315                        GPR64, GPR64, GPR64, 0>;
2317   // Register/register aliases with no shift when the first source register
2318   // is SP.
2319   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2320                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2321   def : AddSubRegAlias<mnemonic,
2322                        !cast<Instruction>(NAME#"Xrx64"),
2323                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2326 class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2327       : BaseAddSubImm<
2328           isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2329           (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2330           (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2331   bits<6> imm6;
2332   bits<4> imm4;
2333   let Inst{31} = 1;
2334   let Inst{23-22} = 0b10;
2335   let Inst{21-16} = imm6;
2336   let Inst{15-14} = 0b00;
2337   let Inst{13-10} = imm4;
2338   let Unpredictable{15-14} = 0b11;
2341 class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2342       : BaseTwoOperand<0b0000, GPR64, asm_instr, null_frag, GPR64sp, GPR64sp> {
2343   let Inst{31} = 1;
2344   let Inst{29} = setsFlags;
2347 //---
2348 // Extract
2349 //---
2350 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2351                                       SDTCisPtrTy<3>]>;
2352 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2354 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2355                      list<dag> patterns>
2356     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2357          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2358       Sched<[WriteExtr, ReadExtrHi]> {
2359   bits<5> Rd;
2360   bits<5> Rn;
2361   bits<5> Rm;
2362   bits<6> imm;
2364   let Inst{30-23} = 0b00100111;
2365   let Inst{21}    = 0;
2366   let Inst{20-16} = Rm;
2367   let Inst{15-10} = imm;
2368   let Inst{9-5}   = Rn;
2369   let Inst{4-0}   = Rd;
2372 multiclass ExtractImm<string asm> {
2373   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2374                       [(set GPR32:$Rd,
2375                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2376     let Inst{31} = 0;
2377     let Inst{22} = 0;
2378     // imm<5> must be zero.
2379     let imm{5}   = 0;
2380   }
2381   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2382                       [(set GPR64:$Rd,
2383                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2385     let Inst{31} = 1;
2386     let Inst{22} = 1;
2387   }
2390 //---
2391 // Bitfield
2392 //---
2394 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2395 class BaseBitfieldImm<bits<2> opc,
2396                       RegisterClass regtype, Operand imm_type, string asm>
2397     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2398          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2399       Sched<[WriteIS, ReadI]> {
2400   bits<5> Rd;
2401   bits<5> Rn;
2402   bits<6> immr;
2403   bits<6> imms;
2405   let Inst{30-29} = opc;
2406   let Inst{28-23} = 0b100110;
2407   let Inst{21-16} = immr;
2408   let Inst{15-10} = imms;
2409   let Inst{9-5}   = Rn;
2410   let Inst{4-0}   = Rd;
2413 multiclass BitfieldImm<bits<2> opc, string asm> {
2414   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2415     let Inst{31} = 0;
2416     let Inst{22} = 0;
2417     // imms<5> and immr<5> must be zero, else ReservedValue().
2418     let Inst{21} = 0;
2419     let Inst{15} = 0;
2420   }
2421   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2422     let Inst{31} = 1;
2423     let Inst{22} = 1;
2424   }
2427 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2428 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2429                       RegisterClass regtype, Operand imm_type, string asm>
2430     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2431                              imm_type:$imms),
2432          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2433       Sched<[WriteIS, ReadI]> {
2434   bits<5> Rd;
2435   bits<5> Rn;
2436   bits<6> immr;
2437   bits<6> imms;
2439   let Inst{30-29} = opc;
2440   let Inst{28-23} = 0b100110;
2441   let Inst{21-16} = immr;
2442   let Inst{15-10} = imms;
2443   let Inst{9-5}   = Rn;
2444   let Inst{4-0}   = Rd;
2447 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2448   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2449     let Inst{31} = 0;
2450     let Inst{22} = 0;
2451     // imms<5> and immr<5> must be zero, else ReservedValue().
2452     let Inst{21} = 0;
2453     let Inst{15} = 0;
2454   }
2455   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2456     let Inst{31} = 1;
2457     let Inst{22} = 1;
2458   }
2461 //---
2462 // Logical
2463 //---
2465 // Logical (immediate)
2466 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2467                      RegisterClass sregtype, Operand imm_type, string asm,
2468                      list<dag> pattern>
2469     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2470          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2471       Sched<[WriteI, ReadI]> {
2472   bits<5>  Rd;
2473   bits<5>  Rn;
2474   bits<13> imm;
2475   let Inst{30-29} = opc;
2476   let Inst{28-23} = 0b100100;
2477   let Inst{22}    = imm{12};
2478   let Inst{21-16} = imm{11-6};
2479   let Inst{15-10} = imm{5-0};
2480   let Inst{9-5}   = Rn;
2481   let Inst{4-0}   = Rd;
2483   let DecoderMethod = "DecodeLogicalImmInstruction";
2486 // Logical (shifted register)
2487 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2488                       logical_shifted_reg shifted_regtype, string asm,
2489                       list<dag> pattern>
2490     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2491         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2492       Sched<[WriteISReg, ReadI, ReadISReg]> {
2493   // The operands are in order to match the 'addr' MI operands, so we
2494   // don't need an encoder method and by-name matching. Just use the default
2495   // in-order handling. Since we're using by-order, make sure the names
2496   // do not match.
2497   bits<5> dst;
2498   bits<5> src1;
2499   bits<5> src2;
2500   bits<8> shift;
2501   let Inst{30-29} = opc;
2502   let Inst{28-24} = 0b01010;
2503   let Inst{23-22} = shift{7-6};
2504   let Inst{21}    = N;
2505   let Inst{20-16} = src2;
2506   let Inst{15-10} = shift{5-0};
2507   let Inst{9-5}   = src1;
2508   let Inst{4-0}   = dst;
2510   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2513 // Aliases for register+register logical instructions.
2514 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2515     : InstAlias<asm#"\t$dst, $src1, $src2",
2516                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2518 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2519                       string Alias> {
2520   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2521   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2522                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2523                                                logical_imm32:$imm))]> {
2524     let Inst{31} = 0;
2525     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2526   }
2527   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2528   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2529                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2530                                                logical_imm64:$imm))]> {
2531     let Inst{31} = 1;
2532   }
2534   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2535                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2536                       logical_imm32_not:$imm), 0>;
2537   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2538                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2539                        logical_imm64_not:$imm), 0>;
2542 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2543                        string Alias> {
2544   let isCompare = 1, Defs = [NZCV] in {
2545   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2546       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2547     let Inst{31} = 0;
2548     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2549   }
2550   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2551       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2552     let Inst{31} = 1;
2553   }
2554   } // end Defs = [NZCV]
2556   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2557                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2558                       logical_imm32_not:$imm), 0>;
2559   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2560                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2561                        logical_imm64_not:$imm), 0>;
2564 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2565     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2566              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2567       Sched<[WriteI, ReadI, ReadI]>;
2569 // Split from LogicalImm as not all instructions have both.
2570 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2571                       SDPatternOperator OpNode> {
2572   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2573   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2574   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2575   }
2577   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2578                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2579                                                  logical_shifted_reg32:$Rm))]> {
2580     let Inst{31} = 0;
2581   }
2582   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2583                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2584                                                  logical_shifted_reg64:$Rm))]> {
2585     let Inst{31} = 1;
2586   }
2588   def : LogicalRegAlias<mnemonic,
2589                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2590   def : LogicalRegAlias<mnemonic,
2591                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2594 // Split from LogicalReg to allow setting NZCV Defs
2595 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2596                        SDPatternOperator OpNode = null_frag> {
2597   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2598   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2599   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2601   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2602             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2603     let Inst{31} = 0;
2604   }
2605   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2606             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2607     let Inst{31} = 1;
2608   }
2609   } // Defs = [NZCV]
2611   def : LogicalRegAlias<mnemonic,
2612                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2613   def : LogicalRegAlias<mnemonic,
2614                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2617 //---
2618 // Conditionally set flags
2619 //---
2621 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2622 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2623                             string mnemonic, SDNode OpNode>
2624     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2625          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2626          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2627                              (i32 imm:$cond), NZCV))]>,
2628       Sched<[WriteI, ReadI]> {
2629   let Uses = [NZCV];
2630   let Defs = [NZCV];
2632   bits<5> Rn;
2633   bits<5> imm;
2634   bits<4> nzcv;
2635   bits<4> cond;
2637   let Inst{30}    = op;
2638   let Inst{29-21} = 0b111010010;
2639   let Inst{20-16} = imm;
2640   let Inst{15-12} = cond;
2641   let Inst{11-10} = 0b10;
2642   let Inst{9-5}   = Rn;
2643   let Inst{4}     = 0b0;
2644   let Inst{3-0}   = nzcv;
2647 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2648 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2649                             SDNode OpNode>
2650     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2651          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2652          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2653                              (i32 imm:$cond), NZCV))]>,
2654       Sched<[WriteI, ReadI, ReadI]> {
2655   let Uses = [NZCV];
2656   let Defs = [NZCV];
2658   bits<5> Rn;
2659   bits<5> Rm;
2660   bits<4> nzcv;
2661   bits<4> cond;
2663   let Inst{30}    = op;
2664   let Inst{29-21} = 0b111010010;
2665   let Inst{20-16} = Rm;
2666   let Inst{15-12} = cond;
2667   let Inst{11-10} = 0b00;
2668   let Inst{9-5}   = Rn;
2669   let Inst{4}     = 0b0;
2670   let Inst{3-0}   = nzcv;
2673 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2674   // immediate operand variants
2675   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2676     let Inst{31} = 0;
2677   }
2678   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2679     let Inst{31} = 1;
2680   }
2681   // register operand variants
2682   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2683     let Inst{31} = 0;
2684   }
2685   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2686     let Inst{31} = 1;
2687   }
2690 //---
2691 // Conditional select
2692 //---
2694 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2695     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2696          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2697          [(set regtype:$Rd,
2698                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2699       Sched<[WriteI, ReadI, ReadI]> {
2700   let Uses = [NZCV];
2702   bits<5> Rd;
2703   bits<5> Rn;
2704   bits<5> Rm;
2705   bits<4> cond;
2707   let Inst{30}    = op;
2708   let Inst{29-21} = 0b011010100;
2709   let Inst{20-16} = Rm;
2710   let Inst{15-12} = cond;
2711   let Inst{11-10} = op2;
2712   let Inst{9-5}   = Rn;
2713   let Inst{4-0}   = Rd;
2716 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2717   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2718     let Inst{31} = 0;
2719   }
2720   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2721     let Inst{31} = 1;
2722   }
2725 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2726                        PatFrag frag>
2727     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2728          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2729          [(set regtype:$Rd,
2730                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2731                (i32 imm:$cond), NZCV))]>,
2732       Sched<[WriteI, ReadI, ReadI]> {
2733   let Uses = [NZCV];
2735   bits<5> Rd;
2736   bits<5> Rn;
2737   bits<5> Rm;
2738   bits<4> cond;
2740   let Inst{30}    = op;
2741   let Inst{29-21} = 0b011010100;
2742   let Inst{20-16} = Rm;
2743   let Inst{15-12} = cond;
2744   let Inst{11-10} = op2;
2745   let Inst{9-5}   = Rn;
2746   let Inst{4-0}   = Rd;
2749 def inv_cond_XFORM : SDNodeXForm<imm, [{
2750   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2751   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2752                                    MVT::i32);
2753 }]>;
2755 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2756   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2757     let Inst{31} = 0;
2758   }
2759   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2760     let Inst{31} = 1;
2761   }
2763   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2764             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2765                                            (inv_cond_XFORM imm:$cond))>;
2767   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2768             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2769                                            (inv_cond_XFORM imm:$cond))>;
2772 //---
2773 // Special Mask Value
2774 //---
2775 def maski8_or_more : Operand<i32>,
2776   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2778 def maski16_or_more : Operand<i32>,
2779   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2783 //---
2784 // Load/store
2785 //---
2787 // (unsigned immediate)
2788 // Indexed for 8-bit registers. offset is in range [0,4095].
2789 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2790 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2791 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2792 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2793 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2795 def gi_am_indexed8 :
2796     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2797     GIComplexPatternEquiv<am_indexed8>;
2798 def gi_am_indexed16 :
2799     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2800     GIComplexPatternEquiv<am_indexed16>;
2801 def gi_am_indexed32 :
2802     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2803     GIComplexPatternEquiv<am_indexed32>;
2804 def gi_am_indexed64 :
2805     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2806     GIComplexPatternEquiv<am_indexed64>;
2807 def gi_am_indexed128 :
2808     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2809     GIComplexPatternEquiv<am_indexed128>;
2811 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2812   let Name = "UImm12Offset" # Scale;
2813   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2814   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2815   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2818 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2819 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2820 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2821 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2822 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2824 class uimm12_scaled<int Scale> : Operand<i64> {
2825   let ParserMatchClass
2826    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2827   let EncoderMethod
2828    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2829   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2832 def uimm12s1 : uimm12_scaled<1>;
2833 def uimm12s2 : uimm12_scaled<2>;
2834 def uimm12s4 : uimm12_scaled<4>;
2835 def uimm12s8 : uimm12_scaled<8>;
2836 def uimm12s16 : uimm12_scaled<16>;
2838 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2839                       string asm, list<dag> pattern>
2840     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2841   bits<5> Rt;
2843   bits<5> Rn;
2844   bits<12> offset;
2846   let Inst{31-30} = sz;
2847   let Inst{29-27} = 0b111;
2848   let Inst{26}    = V;
2849   let Inst{25-24} = 0b01;
2850   let Inst{23-22} = opc;
2851   let Inst{21-10} = offset;
2852   let Inst{9-5}   = Rn;
2853   let Inst{4-0}   = Rt;
2855   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2858 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2859                   Operand indextype, string asm, list<dag> pattern> {
2860   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2861   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2862                            (ins GPR64sp:$Rn, indextype:$offset),
2863                            asm, pattern>,
2864            Sched<[WriteLD]>;
2866   def : InstAlias<asm # "\t$Rt, [$Rn]",
2867                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2870 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2871              Operand indextype, string asm, list<dag> pattern> {
2872   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2873   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2874                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2875                            asm, pattern>,
2876            Sched<[WriteST]>;
2878   def : InstAlias<asm # "\t$Rt, [$Rn]",
2879                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2882 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2883 // substitute zero-registers automatically.
2885 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2886 //       into StoreUI.
2887 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2888              Operand indextype, string asm, list<dag> pattern> {
2889   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2890   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2891                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2892                            asm, pattern>,
2893            Sched<[WriteST]>;
2895   def : InstAlias<asm # "\t$Rt, [$Rn]",
2896                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2899 def PrefetchOperand : AsmOperandClass {
2900   let Name = "Prefetch";
2901   let ParserMethod = "tryParsePrefetch";
2903 def prfop : Operand<i32> {
2904   let PrintMethod = "printPrefetchOp";
2905   let ParserMatchClass = PrefetchOperand;
2908 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2909 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2910     : BaseLoadStoreUI<sz, V, opc,
2911                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2912                       asm, pat>,
2913       Sched<[WriteLD]>;
2915 //---
2916 // Load literal
2917 //---
2919 // Load literal address: 19-bit immediate. The low two bits of the target
2920 // offset are implied zero and so are not part of the immediate.
2921 def am_ldrlit : Operand<iPTR> {
2922   let EncoderMethod = "getLoadLiteralOpValue";
2923   let DecoderMethod = "DecodePCRelLabel19";
2924   let PrintMethod = "printAlignedLabel";
2925   let ParserMatchClass = PCRelLabel19Operand;
2926   let OperandType = "OPERAND_PCREL";
2929 let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
2930 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
2931     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2932         asm, "\t$Rt, $label", "", pat>,
2933       Sched<[WriteLD]> {
2934   bits<5> Rt;
2935   bits<19> label;
2936   let Inst{31-30} = opc;
2937   let Inst{29-27} = 0b011;
2938   let Inst{26}    = V;
2939   let Inst{25-24} = 0b00;
2940   let Inst{23-5}  = label;
2941   let Inst{4-0}   = Rt;
2944 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2945 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2946     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2947         asm, "\t$Rt, $label", "", pat>,
2948       Sched<[WriteLD]> {
2949   bits<5> Rt;
2950   bits<19> label;
2951   let Inst{31-30} = opc;
2952   let Inst{29-27} = 0b011;
2953   let Inst{26}    = V;
2954   let Inst{25-24} = 0b00;
2955   let Inst{23-5}  = label;
2956   let Inst{4-0}   = Rt;
2959 //---
2960 // Load/store register offset
2961 //---
2963 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2964 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2965 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2966 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2967 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2969 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2970 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2971 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2972 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2973 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2975 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2976   let Name = "Mem" # Reg # "Extend" # Width;
2977   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2978   let RenderMethod = "addMemExtendOperands";
2979   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2982 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2983   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2984   // the trivial shift.
2985   let RenderMethod = "addMemExtend8Operands";
2987 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2988 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2989 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2990 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2992 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2993   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2994   // the trivial shift.
2995   let RenderMethod = "addMemExtend8Operands";
2997 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2998 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2999 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3000 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3002 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3003         : Operand<i32> {
3004   let ParserMatchClass = ParserClass;
3005   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3006   let DecoderMethod = "DecodeMemExtend";
3007   let EncoderMethod = "getMemExtendOpValue";
3008   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3011 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3012 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3013 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3014 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3015 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3017 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3018 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3019 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3020 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3021 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3023 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3024                   Operand wextend, Operand xextend>  {
3025   // CodeGen-level pattern covering the entire addressing mode.
3026   ComplexPattern Wpat = windex;
3027   ComplexPattern Xpat = xindex;
3029   // Asm-level Operand covering the valid "uxtw #3" style syntax.
3030   Operand Wext = wextend;
3031   Operand Xext = xextend;
3034 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3035 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3036 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3037 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3038 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3039                        ro_Xextend128>;
3041 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3042                       string asm, dag ins, dag outs, list<dag> pat>
3043     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3044   bits<5> Rt;
3045   bits<5> Rn;
3046   bits<5> Rm;
3047   bits<2> extend;
3048   let Inst{31-30} = sz;
3049   let Inst{29-27} = 0b111;
3050   let Inst{26}    = V;
3051   let Inst{25-24} = 0b00;
3052   let Inst{23-22} = opc;
3053   let Inst{21}    = 1;
3054   let Inst{20-16} = Rm;
3055   let Inst{15}    = extend{1}; // sign extend Rm?
3056   let Inst{14}    = 1;
3057   let Inst{12}    = extend{0}; // do shift?
3058   let Inst{11-10} = 0b10;
3059   let Inst{9-5}   = Rn;
3060   let Inst{4-0}   = Rt;
3063 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3064   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3065               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3067 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3068                    string asm, ValueType Ty, SDPatternOperator loadop> {
3069   let AddedComplexity = 10 in
3070   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3071                  (outs regtype:$Rt),
3072                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3073                  [(set (Ty regtype:$Rt),
3074                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3075                                              ro_Wextend8:$extend)))]>,
3076            Sched<[WriteLDIdx, ReadAdrBase]> {
3077     let Inst{13} = 0b0;
3078   }
3080   let AddedComplexity = 10 in
3081   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3082                  (outs regtype:$Rt),
3083                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3084                  [(set (Ty regtype:$Rt),
3085                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3086                                              ro_Xextend8:$extend)))]>,
3087            Sched<[WriteLDIdx, ReadAdrBase]> {
3088     let Inst{13} = 0b1;
3089   }
3091   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3094 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3095                     string asm, ValueType Ty, SDPatternOperator storeop> {
3096   let AddedComplexity = 10 in
3097   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3098                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3099                  [(storeop (Ty regtype:$Rt),
3100                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3101                                          ro_Wextend8:$extend))]>,
3102             Sched<[WriteSTIdx, ReadAdrBase]> {
3103     let Inst{13} = 0b0;
3104   }
3106   let AddedComplexity = 10 in
3107   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3108                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3109                  [(storeop (Ty regtype:$Rt),
3110                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3111                                          ro_Xextend8:$extend))]>,
3112             Sched<[WriteSTIdx, ReadAdrBase]> {
3113     let Inst{13} = 0b1;
3114   }
3116   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3119 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3120                       string asm, dag ins, dag outs, list<dag> pat>
3121     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3122   bits<5> Rt;
3123   bits<5> Rn;
3124   bits<5> Rm;
3125   bits<2> extend;
3126   let Inst{31-30} = sz;
3127   let Inst{29-27} = 0b111;
3128   let Inst{26}    = V;
3129   let Inst{25-24} = 0b00;
3130   let Inst{23-22} = opc;
3131   let Inst{21}    = 1;
3132   let Inst{20-16} = Rm;
3133   let Inst{15}    = extend{1}; // sign extend Rm?
3134   let Inst{14}    = 1;
3135   let Inst{12}    = extend{0}; // do shift?
3136   let Inst{11-10} = 0b10;
3137   let Inst{9-5}   = Rn;
3138   let Inst{4-0}   = Rt;
3141 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3142                     string asm, ValueType Ty, SDPatternOperator loadop> {
3143   let AddedComplexity = 10 in
3144   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3145                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3146                  [(set (Ty regtype:$Rt),
3147                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3148                                               ro_Wextend16:$extend)))]>,
3149             Sched<[WriteLDIdx, ReadAdrBase]> {
3150     let Inst{13} = 0b0;
3151   }
3153   let AddedComplexity = 10 in
3154   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3155                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3156                  [(set (Ty regtype:$Rt),
3157                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3158                                              ro_Xextend16:$extend)))]>,
3159             Sched<[WriteLDIdx, ReadAdrBase]> {
3160     let Inst{13} = 0b1;
3161   }
3163   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3166 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3167                      string asm, ValueType Ty, SDPatternOperator storeop> {
3168   let AddedComplexity = 10 in
3169   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3170                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3171                 [(storeop (Ty regtype:$Rt),
3172                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3173                                          ro_Wextend16:$extend))]>,
3174            Sched<[WriteSTIdx, ReadAdrBase]> {
3175     let Inst{13} = 0b0;
3176   }
3178   let AddedComplexity = 10 in
3179   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3180                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3181                 [(storeop (Ty regtype:$Rt),
3182                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3183                                          ro_Xextend16:$extend))]>,
3184            Sched<[WriteSTIdx, ReadAdrBase]> {
3185     let Inst{13} = 0b1;
3186   }
3188   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3191 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3192                       string asm, dag ins, dag outs, list<dag> pat>
3193     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3194   bits<5> Rt;
3195   bits<5> Rn;
3196   bits<5> Rm;
3197   bits<2> extend;
3198   let Inst{31-30} = sz;
3199   let Inst{29-27} = 0b111;
3200   let Inst{26}    = V;
3201   let Inst{25-24} = 0b00;
3202   let Inst{23-22} = opc;
3203   let Inst{21}    = 1;
3204   let Inst{20-16} = Rm;
3205   let Inst{15}    = extend{1}; // sign extend Rm?
3206   let Inst{14}    = 1;
3207   let Inst{12}    = extend{0}; // do shift?
3208   let Inst{11-10} = 0b10;
3209   let Inst{9-5}   = Rn;
3210   let Inst{4-0}   = Rt;
3213 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3214                     string asm, ValueType Ty, SDPatternOperator loadop> {
3215   let AddedComplexity = 10 in
3216   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3217                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3218                  [(set (Ty regtype:$Rt),
3219                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3220                                               ro_Wextend32:$extend)))]>,
3221            Sched<[WriteLDIdx, ReadAdrBase]> {
3222     let Inst{13} = 0b0;
3223   }
3225   let AddedComplexity = 10 in
3226   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3227                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3228                  [(set (Ty regtype:$Rt),
3229                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3230                                               ro_Xextend32:$extend)))]>,
3231            Sched<[WriteLDIdx, ReadAdrBase]> {
3232     let Inst{13} = 0b1;
3233   }
3235   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3238 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3239                      string asm, ValueType Ty, SDPatternOperator storeop> {
3240   let AddedComplexity = 10 in
3241   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3242                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3243                 [(storeop (Ty regtype:$Rt),
3244                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3245                                          ro_Wextend32:$extend))]>,
3246             Sched<[WriteSTIdx, ReadAdrBase]> {
3247     let Inst{13} = 0b0;
3248   }
3250   let AddedComplexity = 10 in
3251   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3252                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3253                 [(storeop (Ty regtype:$Rt),
3254                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3255                                         ro_Xextend32:$extend))]>,
3256             Sched<[WriteSTIdx, ReadAdrBase]> {
3257     let Inst{13} = 0b1;
3258   }
3260   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3263 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3264                       string asm, dag ins, dag outs, list<dag> pat>
3265     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3266   bits<5> Rt;
3267   bits<5> Rn;
3268   bits<5> Rm;
3269   bits<2> extend;
3270   let Inst{31-30} = sz;
3271   let Inst{29-27} = 0b111;
3272   let Inst{26}    = V;
3273   let Inst{25-24} = 0b00;
3274   let Inst{23-22} = opc;
3275   let Inst{21}    = 1;
3276   let Inst{20-16} = Rm;
3277   let Inst{15}    = extend{1}; // sign extend Rm?
3278   let Inst{14}    = 1;
3279   let Inst{12}    = extend{0}; // do shift?
3280   let Inst{11-10} = 0b10;
3281   let Inst{9-5}   = Rn;
3282   let Inst{4-0}   = Rt;
3285 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3286                     string asm, ValueType Ty, SDPatternOperator loadop> {
3287   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3288   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3289                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3290                 [(set (Ty regtype:$Rt),
3291                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3292                                              ro_Wextend64:$extend)))]>,
3293            Sched<[WriteLDIdx, ReadAdrBase]> {
3294     let Inst{13} = 0b0;
3295   }
3297   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3298   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3299                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3300                  [(set (Ty regtype:$Rt),
3301                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3302                                               ro_Xextend64:$extend)))]>,
3303            Sched<[WriteLDIdx, ReadAdrBase]> {
3304     let Inst{13} = 0b1;
3305   }
3307   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3310 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3311                      string asm, ValueType Ty, SDPatternOperator storeop> {
3312   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3313   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3314                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3315                 [(storeop (Ty regtype:$Rt),
3316                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3317                                          ro_Wextend64:$extend))]>,
3318             Sched<[WriteSTIdx, ReadAdrBase]> {
3319     let Inst{13} = 0b0;
3320   }
3322   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3323   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3324                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3325                 [(storeop (Ty regtype:$Rt),
3326                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3327                                          ro_Xextend64:$extend))]>,
3328             Sched<[WriteSTIdx, ReadAdrBase]> {
3329     let Inst{13} = 0b1;
3330   }
3332   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3335 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3336                       string asm, dag ins, dag outs, list<dag> pat>
3337     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3338   bits<5> Rt;
3339   bits<5> Rn;
3340   bits<5> Rm;
3341   bits<2> extend;
3342   let Inst{31-30} = sz;
3343   let Inst{29-27} = 0b111;
3344   let Inst{26}    = V;
3345   let Inst{25-24} = 0b00;
3346   let Inst{23-22} = opc;
3347   let Inst{21}    = 1;
3348   let Inst{20-16} = Rm;
3349   let Inst{15}    = extend{1}; // sign extend Rm?
3350   let Inst{14}    = 1;
3351   let Inst{12}    = extend{0}; // do shift?
3352   let Inst{11-10} = 0b10;
3353   let Inst{9-5}   = Rn;
3354   let Inst{4-0}   = Rt;
3357 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3358                      string asm, ValueType Ty, SDPatternOperator loadop> {
3359   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3360   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3361                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3362                  [(set (Ty regtype:$Rt),
3363                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3364                                                ro_Wextend128:$extend)))]>,
3365             Sched<[WriteLDIdx, ReadAdrBase]> {
3366     let Inst{13} = 0b0;
3367   }
3369   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3370   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3371                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3372                  [(set (Ty regtype:$Rt),
3373                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3374                                                ro_Xextend128:$extend)))]>,
3375             Sched<[WriteLDIdx, ReadAdrBase]> {
3376     let Inst{13} = 0b1;
3377   }
3379   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3382 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3383                       string asm, ValueType Ty, SDPatternOperator storeop> {
3384   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3385   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3386                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3387                 []>,
3388             Sched<[WriteSTIdx, ReadAdrBase]> {
3389     let Inst{13} = 0b0;
3390   }
3392   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3393   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3394                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3395                 []>,
3396             Sched<[WriteSTIdx, ReadAdrBase]> {
3397     let Inst{13} = 0b1;
3398   }
3400   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3403 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3404 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3405                      string asm, list<dag> pat>
3406     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3407       Sched<[WriteLD]> {
3408   bits<5> Rt;
3409   bits<5> Rn;
3410   bits<5> Rm;
3411   bits<2> extend;
3412   let Inst{31-30} = sz;
3413   let Inst{29-27} = 0b111;
3414   let Inst{26}    = V;
3415   let Inst{25-24} = 0b00;
3416   let Inst{23-22} = opc;
3417   let Inst{21}    = 1;
3418   let Inst{20-16} = Rm;
3419   let Inst{15}    = extend{1}; // sign extend Rm?
3420   let Inst{14}    = 1;
3421   let Inst{12}    = extend{0}; // do shift?
3422   let Inst{11-10} = 0b10;
3423   let Inst{9-5}   = Rn;
3424   let Inst{4-0}   = Rt;
3427 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3428   def roW : BasePrefetchRO<sz, V, opc, (outs),
3429                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3430                 asm, [(AArch64Prefetch imm:$Rt,
3431                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3432                                                     ro_Wextend64:$extend))]> {
3433     let Inst{13} = 0b0;
3434   }
3436   def roX : BasePrefetchRO<sz, V, opc, (outs),
3437                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3438                 asm,  [(AArch64Prefetch imm:$Rt,
3439                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3440                                                      ro_Xextend64:$extend))]> {
3441     let Inst{13} = 0b1;
3442   }
3444   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3445                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3446                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3449 //---
3450 // Load/store unscaled immediate
3451 //---
3453 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3454 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3455 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3456 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3457 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3459 def gi_am_unscaled8 :
3460     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3461     GIComplexPatternEquiv<am_unscaled8>;
3462 def gi_am_unscaled16 :
3463     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3464     GIComplexPatternEquiv<am_unscaled16>;
3465 def gi_am_unscaled32 :
3466     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3467     GIComplexPatternEquiv<am_unscaled32>;
3468 def gi_am_unscaled64 :
3469     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3470     GIComplexPatternEquiv<am_unscaled64>;
3471 def gi_am_unscaled128 :
3472     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3473     GIComplexPatternEquiv<am_unscaled128>;
3476 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3477                            string asm, list<dag> pattern>
3478     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3479   bits<5> Rt;
3480   bits<5> Rn;
3481   bits<9> offset;
3482   let Inst{31-30} = sz;
3483   let Inst{29-27} = 0b111;
3484   let Inst{26}    = V;
3485   let Inst{25-24} = 0b00;
3486   let Inst{23-22} = opc;
3487   let Inst{21}    = 0;
3488   let Inst{20-12} = offset;
3489   let Inst{11-10} = 0b00;
3490   let Inst{9-5}   = Rn;
3491   let Inst{4-0}   = Rt;
3493   let DecoderMethod = "DecodeSignedLdStInstruction";
3496 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3497 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3498                               RegisterOperand regtype > {
3499   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3500                                (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3501           Sched<[WriteST]> {
3502     let Inst{29} = 0;
3503     let Inst{24} = 1;
3504   }
3505   def : InstAlias<asm # "\t$Rt, [$Rn]",
3506                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3509 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3510                                RegisterOperand regtype > {
3511   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3512                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3513                                asm, []>,
3514           Sched<[WriteST]> {
3515     let Inst{29} = 0;
3516     let Inst{24} = 1;
3517   }
3518   def : InstAlias<asm # "\t$Rt, [$Rn]",
3519                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3522 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3523                    string asm, list<dag> pattern> {
3524   let AddedComplexity = 1 in // try this before LoadUI
3525   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3526                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3527           Sched<[WriteLD]>;
3529   def : InstAlias<asm # "\t$Rt, [$Rn]",
3530                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3533 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3534                          string asm, list<dag> pattern> {
3535   let AddedComplexity = 1 in // try this before StoreUI
3536   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3537                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3538                                asm, pattern>,
3539           Sched<[WriteST]>;
3541   def : InstAlias<asm # "\t$Rt, [$Rn]",
3542                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3545 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3546                             list<dag> pat> {
3547   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3548   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3549                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3550                                asm, pat>,
3551           Sched<[WriteLD]>;
3553   def : InstAlias<asm # "\t$Rt, [$Rn]",
3554                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3557 //---
3558 // Load/store unscaled immediate, unprivileged
3559 //---
3561 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3562                                 dag oops, dag iops, string asm>
3563     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3564   bits<5> Rt;
3565   bits<5> Rn;
3566   bits<9> offset;
3567   let Inst{31-30} = sz;
3568   let Inst{29-27} = 0b111;
3569   let Inst{26}    = V;
3570   let Inst{25-24} = 0b00;
3571   let Inst{23-22} = opc;
3572   let Inst{21}    = 0;
3573   let Inst{20-12} = offset;
3574   let Inst{11-10} = 0b10;
3575   let Inst{9-5}   = Rn;
3576   let Inst{4-0}   = Rt;
3578   let DecoderMethod = "DecodeSignedLdStInstruction";
3581 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3582                             RegisterClass regtype, string asm> {
3583   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3584   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3585                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3586           Sched<[WriteLD]>;
3588   def : InstAlias<asm # "\t$Rt, [$Rn]",
3589                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3592 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3593                              RegisterClass regtype, string asm> {
3594   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3595   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3596                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3597                                  asm>,
3598           Sched<[WriteST]>;
3600   def : InstAlias<asm # "\t$Rt, [$Rn]",
3601                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3604 //---
3605 // Load/store pre-indexed
3606 //---
3608 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3609                           string asm, string cstr, list<dag> pat>
3610     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3611   bits<5> Rt;
3612   bits<5> Rn;
3613   bits<9> offset;
3614   let Inst{31-30} = sz;
3615   let Inst{29-27} = 0b111;
3616   let Inst{26}    = V;
3617   let Inst{25-24} = 0;
3618   let Inst{23-22} = opc;
3619   let Inst{21}    = 0;
3620   let Inst{20-12} = offset;
3621   let Inst{11-10} = 0b11;
3622   let Inst{9-5}   = Rn;
3623   let Inst{4-0}   = Rt;
3625   let DecoderMethod = "DecodeSignedLdStInstruction";
3628 let hasSideEffects = 0 in {
3629 let mayStore = 0, mayLoad = 1 in
3630 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3631              string asm>
3632     : BaseLoadStorePreIdx<sz, V, opc,
3633                      (outs GPR64sp:$wback, regtype:$Rt),
3634                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3635                      "$Rn = $wback,@earlyclobber $wback", []>,
3636       Sched<[WriteLD, WriteAdr]>;
3638 let mayStore = 1, mayLoad = 0 in
3639 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3640                   string asm, SDPatternOperator storeop, ValueType Ty>
3641     : BaseLoadStorePreIdx<sz, V, opc,
3642                       (outs GPR64sp:$wback),
3643                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3644                       asm, "$Rn = $wback,@earlyclobber $wback",
3645       [(set GPR64sp:$wback,
3646             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3647       Sched<[WriteAdr, WriteST]>;
3648 } // hasSideEffects = 0
3650 //---
3651 // Load/store post-indexed
3652 //---
3654 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3655                           string asm, string cstr, list<dag> pat>
3656     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3657   bits<5> Rt;
3658   bits<5> Rn;
3659   bits<9> offset;
3660   let Inst{31-30} = sz;
3661   let Inst{29-27} = 0b111;
3662   let Inst{26}    = V;
3663   let Inst{25-24} = 0b00;
3664   let Inst{23-22} = opc;
3665   let Inst{21}    = 0b0;
3666   let Inst{20-12} = offset;
3667   let Inst{11-10} = 0b01;
3668   let Inst{9-5}   = Rn;
3669   let Inst{4-0}   = Rt;
3671   let DecoderMethod = "DecodeSignedLdStInstruction";
3674 let hasSideEffects = 0 in {
3675 let mayStore = 0, mayLoad = 1 in
3676 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3677              string asm>
3678     : BaseLoadStorePostIdx<sz, V, opc,
3679                       (outs GPR64sp:$wback, regtype:$Rt),
3680                       (ins GPR64sp:$Rn, simm9:$offset),
3681                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3682       Sched<[WriteLD, WriteAdr]>;
3684 let mayStore = 1, mayLoad = 0 in
3685 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3686                    string asm, SDPatternOperator storeop, ValueType Ty>
3687     : BaseLoadStorePostIdx<sz, V, opc,
3688                       (outs GPR64sp:$wback),
3689                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3690                        asm, "$Rn = $wback,@earlyclobber $wback",
3691       [(set GPR64sp:$wback,
3692             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3693     Sched<[WriteAdr, WriteST]>;
3694 } // hasSideEffects = 0
3697 //---
3698 // Load/store pair
3699 //---
3701 // (indexed, offset)
3703 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3704                               string asm>
3705     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3706   bits<5> Rt;
3707   bits<5> Rt2;
3708   bits<5> Rn;
3709   bits<7> offset;
3710   let Inst{31-30} = opc;
3711   let Inst{29-27} = 0b101;
3712   let Inst{26}    = V;
3713   let Inst{25-23} = 0b010;
3714   let Inst{22}    = L;
3715   let Inst{21-15} = offset;
3716   let Inst{14-10} = Rt2;
3717   let Inst{9-5}   = Rn;
3718   let Inst{4-0}   = Rt;
3720   let DecoderMethod = "DecodePairLdStInstruction";
3723 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3724                           Operand indextype, string asm> {
3725   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3726   def i : BaseLoadStorePairOffset<opc, V, 1,
3727                                   (outs regtype:$Rt, regtype:$Rt2),
3728                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3729           Sched<[WriteLD, WriteLDHi]>;
3731   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3732                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3733                                                   GPR64sp:$Rn, 0)>;
3737 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3738                            Operand indextype, string asm> {
3739   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3740   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3741                                   (ins regtype:$Rt, regtype:$Rt2,
3742                                        GPR64sp:$Rn, indextype:$offset),
3743                                   asm>,
3744           Sched<[WriteSTP]>;
3746   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3747                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3748                                                   GPR64sp:$Rn, 0)>;
3751 // (pre-indexed)
3752 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3753                               string asm>
3754     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3755   bits<5> Rt;
3756   bits<5> Rt2;
3757   bits<5> Rn;
3758   bits<7> offset;
3759   let Inst{31-30} = opc;
3760   let Inst{29-27} = 0b101;
3761   let Inst{26}    = V;
3762   let Inst{25-23} = 0b011;
3763   let Inst{22}    = L;
3764   let Inst{21-15} = offset;
3765   let Inst{14-10} = Rt2;
3766   let Inst{9-5}   = Rn;
3767   let Inst{4-0}   = Rt;
3769   let DecoderMethod = "DecodePairLdStInstruction";
3772 let hasSideEffects = 0 in {
3773 let mayStore = 0, mayLoad = 1 in
3774 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3775                      Operand indextype, string asm>
3776     : BaseLoadStorePairPreIdx<opc, V, 1,
3777                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3778                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3779       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3781 let mayStore = 1, mayLoad = 0 in
3782 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3783                       Operand indextype, string asm>
3784     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3785                              (ins regtype:$Rt, regtype:$Rt2,
3786                                   GPR64sp:$Rn, indextype:$offset),
3787                              asm>,
3788       Sched<[WriteAdr, WriteSTP]>;
3789 } // hasSideEffects = 0
3791 // (post-indexed)
3793 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3794                               string asm>
3795     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3796   bits<5> Rt;
3797   bits<5> Rt2;
3798   bits<5> Rn;
3799   bits<7> offset;
3800   let Inst{31-30} = opc;
3801   let Inst{29-27} = 0b101;
3802   let Inst{26}    = V;
3803   let Inst{25-23} = 0b001;
3804   let Inst{22}    = L;
3805   let Inst{21-15} = offset;
3806   let Inst{14-10} = Rt2;
3807   let Inst{9-5}   = Rn;
3808   let Inst{4-0}   = Rt;
3810   let DecoderMethod = "DecodePairLdStInstruction";
3813 let hasSideEffects = 0 in {
3814 let mayStore = 0, mayLoad = 1 in
3815 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3816                       Operand idxtype, string asm>
3817     : BaseLoadStorePairPostIdx<opc, V, 1,
3818                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3819                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3820       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3822 let mayStore = 1, mayLoad = 0 in
3823 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3824                        Operand idxtype, string asm>
3825     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3826                              (ins regtype:$Rt, regtype:$Rt2,
3827                                   GPR64sp:$Rn, idxtype:$offset),
3828                              asm>,
3829       Sched<[WriteAdr, WriteSTP]>;
3830 } // hasSideEffects = 0
3832 //  (no-allocate)
3834 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3835                               string asm>
3836     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3837   bits<5> Rt;
3838   bits<5> Rt2;
3839   bits<5> Rn;
3840   bits<7> offset;
3841   let Inst{31-30} = opc;
3842   let Inst{29-27} = 0b101;
3843   let Inst{26}    = V;
3844   let Inst{25-23} = 0b000;
3845   let Inst{22}    = L;
3846   let Inst{21-15} = offset;
3847   let Inst{14-10} = Rt2;
3848   let Inst{9-5}   = Rn;
3849   let Inst{4-0}   = Rt;
3851   let DecoderMethod = "DecodePairLdStInstruction";
3854 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3855                            Operand indextype, string asm> {
3856   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3857   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3858                                    (outs regtype:$Rt, regtype:$Rt2),
3859                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3860           Sched<[WriteLD, WriteLDHi]>;
3863   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3864                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3865                                                   GPR64sp:$Rn, 0)>;
3868 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3869                       Operand indextype, string asm> {
3870   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3871   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3872                                    (ins regtype:$Rt, regtype:$Rt2,
3873                                         GPR64sp:$Rn, indextype:$offset),
3874                                    asm>,
3875           Sched<[WriteSTP]>;
3877   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3878                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3879                                                   GPR64sp:$Rn, 0)>;
3882 //---
3883 // Load/store exclusive
3884 //---
3886 // True exclusive operations write to and/or read from the system's exclusive
3887 // monitors, which as far as a compiler is concerned can be modelled as a
3888 // random shared memory address. Hence LoadExclusive mayStore.
3890 // Since these instructions have the undefined register bits set to 1 in
3891 // their canonical form, we need a post encoder method to set those bits
3892 // to 1 when encoding these instructions. We do this using the
3893 // fixLoadStoreExclusive function. This function has template parameters:
3895 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3897 // hasRs indicates that the instruction uses the Rs field, so we won't set
3898 // it to 1 (and the same for Rt2). We don't need template parameters for
3899 // the other register fields since Rt and Rn are always used.
3901 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3902 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3903                              dag oops, dag iops, string asm, string operands>
3904     : I<oops, iops, asm, operands, "", []> {
3905   let Inst{31-30} = sz;
3906   let Inst{29-24} = 0b001000;
3907   let Inst{23}    = o2;
3908   let Inst{22}    = L;
3909   let Inst{21}    = o1;
3910   let Inst{15}    = o0;
3912   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3915 // Neither Rs nor Rt2 operands.
3916 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3917                                dag oops, dag iops, string asm, string operands>
3918     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3919   bits<5> Rt;
3920   bits<5> Rn;
3921   let Inst{20-16} = 0b11111;
3922   let Unpredictable{20-16} = 0b11111;
3923   let Inst{14-10} = 0b11111;
3924   let Unpredictable{14-10} = 0b11111;
3925   let Inst{9-5} = Rn;
3926   let Inst{4-0} = Rt;
3928   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3931 // Simple load acquires don't set the exclusive monitor
3932 let mayLoad = 1, mayStore = 0 in
3933 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3934                   RegisterClass regtype, string asm>
3935     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3936                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3937       Sched<[WriteLD]>;
3939 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3940                     RegisterClass regtype, string asm>
3941     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3942                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3943       Sched<[WriteLD]>;
3945 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3946                        RegisterClass regtype, string asm>
3947     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3948                              (outs regtype:$Rt, regtype:$Rt2),
3949                              (ins GPR64sp0:$Rn), asm,
3950                              "\t$Rt, $Rt2, [$Rn]">,
3951       Sched<[WriteLD, WriteLDHi]> {
3952   bits<5> Rt;
3953   bits<5> Rt2;
3954   bits<5> Rn;
3955   let Inst{14-10} = Rt2;
3956   let Inst{9-5} = Rn;
3957   let Inst{4-0} = Rt;
3959   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3962 // Simple store release operations do not check the exclusive monitor.
3963 let mayLoad = 0, mayStore = 1 in
3964 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3965                    RegisterClass regtype, string asm>
3966     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3967                                (ins regtype:$Rt, GPR64sp0:$Rn),
3968                                asm, "\t$Rt, [$Rn]">,
3969       Sched<[WriteST]>;
3971 let mayLoad = 1, mayStore = 1 in
3972 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3973                      RegisterClass regtype, string asm>
3974     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3975                              (ins regtype:$Rt, GPR64sp0:$Rn),
3976                              asm, "\t$Ws, $Rt, [$Rn]">,
3977       Sched<[WriteSTX]> {
3978   bits<5> Ws;
3979   bits<5> Rt;
3980   bits<5> Rn;
3981   let Inst{20-16} = Ws;
3982   let Inst{9-5} = Rn;
3983   let Inst{4-0} = Rt;
3985   let Constraints = "@earlyclobber $Ws";
3986   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3989 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3990                          RegisterClass regtype, string asm>
3991     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3992                              (outs GPR32:$Ws),
3993                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3994                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3995       Sched<[WriteSTX]> {
3996   bits<5> Ws;
3997   bits<5> Rt;
3998   bits<5> Rt2;
3999   bits<5> Rn;
4000   let Inst{20-16} = Ws;
4001   let Inst{14-10} = Rt2;
4002   let Inst{9-5} = Rn;
4003   let Inst{4-0} = Rt;
4005   let Constraints = "@earlyclobber $Ws";
4008 // Armv8.5-A Memory Tagging Extension
4009 class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4010                  string asm_opnds, string cstr, dag oops, dag iops>
4011     : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4012       Sched<[]> {
4013   bits<5> Rn;
4015   let Inst{31-24} = 0b11011001;
4016   let Inst{23-22} = opc1;
4017   let Inst{21}    = 1;
4018   // Inst{20-12} defined by subclass
4019   let Inst{11-10} = opc2;
4020   let Inst{9-5}   = Rn;
4021   // Inst{4-0} defined by subclass
4024 class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4025                    dag oops, dag iops>
4026     : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4027                  "$Rn = $wback,@earlyclobber $wback", oops, iops> {
4028   bits<5> Rt;
4030   let Inst{20-12} = 0b000000000;
4031   let Inst{4-0}   = Rt;
4033   let mayLoad = Load;
4036 class MemTagLoad<string asm_insn, string asm_opnds>
4037     : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "", (outs GPR64:$Rt),
4038                  (ins GPR64sp:$Rn, simm9s16:$offset)> {
4039   bits<5> Rt;
4040   bits<9> offset;
4042   let Inst{20-12} = offset;
4043   let Inst{4-0}   = Rt;
4045   let mayLoad = 1;
4048 class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4049                      string asm_opnds, string cstr, dag oops, dag iops>
4050     : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4051   bits<5> Rt;
4052   bits<9> offset;
4054   let Inst{20-12} = offset;
4055   let Inst{4-0}   = 0b11111;
4056   let Unpredictable{4-0} = 0b11111;
4058   let mayStore = 1;
4061 multiclass MemTagStore<bits<2> opc1, string insn> {
4062   def Offset :
4063     BaseMemTagStore<opc1, 0b10, insn, "\t[$Rn, $offset]", "",
4064                     (outs), (ins GPR64sp:$Rn, simm9s16:$offset)>;
4065   def PreIndex :
4066     BaseMemTagStore<opc1, 0b11, insn, "\t[$Rn, $offset]!",
4067                     "$Rn = $wback,@earlyclobber $wback",
4068                     (outs GPR64sp:$wback),
4069                     (ins GPR64sp:$Rn, simm9s16:$offset)>;
4070   def PostIndex :
4071     BaseMemTagStore<opc1, 0b01, insn, "\t[$Rn], $offset",
4072                     "$Rn = $wback,@earlyclobber $wback",
4073                     (outs GPR64sp:$wback),
4074                     (ins GPR64sp:$Rn, simm9s16:$offset)>;
4076   def : InstAlias<insn # "\t[$Rn]",
4077                   (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rn, 0)>;
4080 //---
4081 // Exception generation
4082 //---
4084 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4085 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4086     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
4087       Sched<[WriteSys]> {
4088   bits<16> imm;
4089   let Inst{31-24} = 0b11010100;
4090   let Inst{23-21} = op1;
4091   let Inst{20-5}  = imm;
4092   let Inst{4-2}   = 0b000;
4093   let Inst{1-0}   = ll;
4096 //---
4097 // UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4098 //--
4099 let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4100 class UDFType<bits<16> opc, string asm>
4101   : I<(outs), (ins uimm16:$imm),
4102        asm, "\t$imm", "", []>,
4103     Sched<[]> {
4104   bits<16> imm;
4105   let Inst{31-16} = opc;
4106   let Inst{15-0} = imm;
4109 let Predicates = [HasFPARMv8] in {
4111 //---
4112 // Floating point to integer conversion
4113 //---
4115 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4116                       RegisterClass srcType, RegisterClass dstType,
4117                       string asm, list<dag> pattern>
4118     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4119          asm, "\t$Rd, $Rn", "", pattern>,
4120       Sched<[WriteFCvt]> {
4121   bits<5> Rd;
4122   bits<5> Rn;
4123   let Inst{30-29} = 0b00;
4124   let Inst{28-24} = 0b11110;
4125   let Inst{23-22} = type;
4126   let Inst{21}    = 1;
4127   let Inst{20-19} = rmode;
4128   let Inst{18-16} = opcode;
4129   let Inst{15-10} = 0;
4130   let Inst{9-5}   = Rn;
4131   let Inst{4-0}   = Rd;
4134 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4135 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4136                       RegisterClass srcType, RegisterClass dstType,
4137                       Operand immType, string asm, list<dag> pattern>
4138     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4139          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4140       Sched<[WriteFCvt]> {
4141   bits<5> Rd;
4142   bits<5> Rn;
4143   bits<6> scale;
4144   let Inst{30-29} = 0b00;
4145   let Inst{28-24} = 0b11110;
4146   let Inst{23-22} = type;
4147   let Inst{21}    = 0;
4148   let Inst{20-19} = rmode;
4149   let Inst{18-16} = opcode;
4150   let Inst{15-10} = scale;
4151   let Inst{9-5}   = Rn;
4152   let Inst{4-0}   = Rd;
4155 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4156            SDPatternOperator OpN> {
4157   // Unscaled half-precision to 32-bit
4158   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4159                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4160     let Inst{31} = 0; // 32-bit GPR flag
4161     let Predicates = [HasFullFP16];
4162   }
4164   // Unscaled half-precision to 64-bit
4165   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4166                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4167     let Inst{31} = 1; // 64-bit GPR flag
4168     let Predicates = [HasFullFP16];
4169   }
4171   // Unscaled single-precision to 32-bit
4172   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4173                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4174     let Inst{31} = 0; // 32-bit GPR flag
4175   }
4177   // Unscaled single-precision to 64-bit
4178   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4179                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4180     let Inst{31} = 1; // 64-bit GPR flag
4181   }
4183   // Unscaled double-precision to 32-bit
4184   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4185                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4186     let Inst{31} = 0; // 32-bit GPR flag
4187   }
4189   // Unscaled double-precision to 64-bit
4190   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4191                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4192     let Inst{31} = 1; // 64-bit GPR flag
4193   }
4196 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4197                              SDPatternOperator OpN> {
4198   // Scaled half-precision to 32-bit
4199   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4200                               fixedpoint_f16_i32, asm,
4201               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4202                                           fixedpoint_f16_i32:$scale)))]> {
4203     let Inst{31} = 0; // 32-bit GPR flag
4204     let scale{5} = 1;
4205     let Predicates = [HasFullFP16];
4206   }
4208   // Scaled half-precision to 64-bit
4209   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4210                               fixedpoint_f16_i64, asm,
4211               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4212                                           fixedpoint_f16_i64:$scale)))]> {
4213     let Inst{31} = 1; // 64-bit GPR flag
4214     let Predicates = [HasFullFP16];
4215   }
4217   // Scaled single-precision to 32-bit
4218   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4219                               fixedpoint_f32_i32, asm,
4220               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4221                                           fixedpoint_f32_i32:$scale)))]> {
4222     let Inst{31} = 0; // 32-bit GPR flag
4223     let scale{5} = 1;
4224   }
4226   // Scaled single-precision to 64-bit
4227   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4228                               fixedpoint_f32_i64, asm,
4229               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4230                                           fixedpoint_f32_i64:$scale)))]> {
4231     let Inst{31} = 1; // 64-bit GPR flag
4232   }
4234   // Scaled double-precision to 32-bit
4235   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4236                               fixedpoint_f64_i32, asm,
4237               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4238                                           fixedpoint_f64_i32:$scale)))]> {
4239     let Inst{31} = 0; // 32-bit GPR flag
4240     let scale{5} = 1;
4241   }
4243   // Scaled double-precision to 64-bit
4244   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4245                               fixedpoint_f64_i64, asm,
4246               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4247                                           fixedpoint_f64_i64:$scale)))]> {
4248     let Inst{31} = 1; // 64-bit GPR flag
4249   }
4252 //---
4253 // Integer to floating point conversion
4254 //---
4256 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4257 class BaseIntegerToFP<bit isUnsigned,
4258                       RegisterClass srcType, RegisterClass dstType,
4259                       Operand immType, string asm, list<dag> pattern>
4260     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4261          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4262       Sched<[WriteFCvt]> {
4263   bits<5> Rd;
4264   bits<5> Rn;
4265   bits<6> scale;
4266   let Inst{30-24} = 0b0011110;
4267   let Inst{21-17} = 0b00001;
4268   let Inst{16}    = isUnsigned;
4269   let Inst{15-10} = scale;
4270   let Inst{9-5}   = Rn;
4271   let Inst{4-0}   = Rd;
4274 class BaseIntegerToFPUnscaled<bit isUnsigned,
4275                       RegisterClass srcType, RegisterClass dstType,
4276                       ValueType dvt, string asm, SDNode node>
4277     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4278          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4279       Sched<[WriteFCvt]> {
4280   bits<5> Rd;
4281   bits<5> Rn;
4282   bits<6> scale;
4283   let Inst{30-24} = 0b0011110;
4284   let Inst{21-17} = 0b10001;
4285   let Inst{16}    = isUnsigned;
4286   let Inst{15-10} = 0b000000;
4287   let Inst{9-5}   = Rn;
4288   let Inst{4-0}   = Rd;
4291 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4292   // Unscaled
4293   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4294     let Inst{31} = 0; // 32-bit GPR flag
4295     let Inst{23-22} = 0b11; // 16-bit FPR flag
4296     let Predicates = [HasFullFP16];
4297   }
4299   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4300     let Inst{31} = 0; // 32-bit GPR flag
4301     let Inst{23-22} = 0b00; // 32-bit FPR flag
4302   }
4304   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4305     let Inst{31} = 0; // 32-bit GPR flag
4306     let Inst{23-22} = 0b01; // 64-bit FPR flag
4307   }
4309   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4310     let Inst{31} = 1; // 64-bit GPR flag
4311     let Inst{23-22} = 0b11; // 16-bit FPR flag
4312     let Predicates = [HasFullFP16];
4313   }
4315   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4316     let Inst{31} = 1; // 64-bit GPR flag
4317     let Inst{23-22} = 0b00; // 32-bit FPR flag
4318   }
4320   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4321     let Inst{31} = 1; // 64-bit GPR flag
4322     let Inst{23-22} = 0b01; // 64-bit FPR flag
4323   }
4325   // Scaled
4326   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4327                              [(set FPR16:$Rd,
4328                                    (fdiv (node GPR32:$Rn),
4329                                          fixedpoint_f16_i32:$scale))]> {
4330     let Inst{31} = 0; // 32-bit GPR flag
4331     let Inst{23-22} = 0b11; // 16-bit FPR flag
4332     let scale{5} = 1;
4333     let Predicates = [HasFullFP16];
4334   }
4336   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4337                              [(set FPR32:$Rd,
4338                                    (fdiv (node GPR32:$Rn),
4339                                          fixedpoint_f32_i32:$scale))]> {
4340     let Inst{31} = 0; // 32-bit GPR flag
4341     let Inst{23-22} = 0b00; // 32-bit FPR flag
4342     let scale{5} = 1;
4343   }
4345   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4346                              [(set FPR64:$Rd,
4347                                    (fdiv (node GPR32:$Rn),
4348                                          fixedpoint_f64_i32:$scale))]> {
4349     let Inst{31} = 0; // 32-bit GPR flag
4350     let Inst{23-22} = 0b01; // 64-bit FPR flag
4351     let scale{5} = 1;
4352   }
4354   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4355                              [(set FPR16:$Rd,
4356                                    (fdiv (node GPR64:$Rn),
4357                                          fixedpoint_f16_i64:$scale))]> {
4358     let Inst{31} = 1; // 64-bit GPR flag
4359     let Inst{23-22} = 0b11; // 16-bit FPR flag
4360     let Predicates = [HasFullFP16];
4361   }
4363   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4364                              [(set FPR32:$Rd,
4365                                    (fdiv (node GPR64:$Rn),
4366                                          fixedpoint_f32_i64:$scale))]> {
4367     let Inst{31} = 1; // 64-bit GPR flag
4368     let Inst{23-22} = 0b00; // 32-bit FPR flag
4369   }
4371   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4372                              [(set FPR64:$Rd,
4373                                    (fdiv (node GPR64:$Rn),
4374                                          fixedpoint_f64_i64:$scale))]> {
4375     let Inst{31} = 1; // 64-bit GPR flag
4376     let Inst{23-22} = 0b01; // 64-bit FPR flag
4377   }
4380 //---
4381 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4382 //---
4384 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4385 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4386                       RegisterClass srcType, RegisterClass dstType,
4387                       string asm>
4388     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4389         // We use COPY_TO_REGCLASS for these bitconvert operations.
4390         // copyPhysReg() expands the resultant COPY instructions after
4391         // regalloc is done. This gives greater freedom for the allocator
4392         // and related passes (coalescing, copy propagation, et. al.) to
4393         // be more effective.
4394         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4395       Sched<[WriteFCopy]> {
4396   bits<5> Rd;
4397   bits<5> Rn;
4398   let Inst{30-24} = 0b0011110;
4399   let Inst{21}    = 1;
4400   let Inst{20-19} = rmode;
4401   let Inst{18-16} = opcode;
4402   let Inst{15-10} = 0b000000;
4403   let Inst{9-5}   = Rn;
4404   let Inst{4-0}   = Rd;
4407 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4408 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4409                      RegisterClass srcType, RegisterOperand dstType, string asm,
4410                      string kind>
4411     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4412         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4413       Sched<[WriteFCopy]> {
4414   bits<5> Rd;
4415   bits<5> Rn;
4416   let Inst{30-23} = 0b00111101;
4417   let Inst{21}    = 1;
4418   let Inst{20-19} = rmode;
4419   let Inst{18-16} = opcode;
4420   let Inst{15-10} = 0b000000;
4421   let Inst{9-5}   = Rn;
4422   let Inst{4-0}   = Rd;
4424   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4427 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4428 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4429                      RegisterOperand srcType, RegisterClass dstType, string asm,
4430                      string kind>
4431     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4432         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4433       Sched<[WriteFCopy]> {
4434   bits<5> Rd;
4435   bits<5> Rn;
4436   let Inst{30-23} = 0b00111101;
4437   let Inst{21}    = 1;
4438   let Inst{20-19} = rmode;
4439   let Inst{18-16} = opcode;
4440   let Inst{15-10} = 0b000000;
4441   let Inst{9-5}   = Rn;
4442   let Inst{4-0}   = Rd;
4444   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4448 multiclass UnscaledConversion<string asm> {
4449   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4450     let Inst{31} = 0; // 32-bit GPR flag
4451     let Inst{23-22} = 0b11; // 16-bit FPR flag
4452     let Predicates = [HasFullFP16];
4453   }
4455   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4456     let Inst{31} = 1; // 64-bit GPR flag
4457     let Inst{23-22} = 0b11; // 16-bit FPR flag
4458     let Predicates = [HasFullFP16];
4459   }
4461   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4462     let Inst{31} = 0; // 32-bit GPR flag
4463     let Inst{23-22} = 0b00; // 32-bit FPR flag
4464   }
4466   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4467     let Inst{31} = 1; // 64-bit GPR flag
4468     let Inst{23-22} = 0b01; // 64-bit FPR flag
4469   }
4471   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4472     let Inst{31} = 0; // 32-bit GPR flag
4473     let Inst{23-22} = 0b11; // 16-bit FPR flag
4474     let Predicates = [HasFullFP16];
4475   }
4477   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4478     let Inst{31} = 1; // 64-bit GPR flag
4479     let Inst{23-22} = 0b11; // 16-bit FPR flag
4480     let Predicates = [HasFullFP16];
4481   }
4483   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4484     let Inst{31} = 0; // 32-bit GPR flag
4485     let Inst{23-22} = 0b00; // 32-bit FPR flag
4486   }
4488   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4489     let Inst{31} = 1; // 64-bit GPR flag
4490     let Inst{23-22} = 0b01; // 64-bit FPR flag
4491   }
4493   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4494                                              asm, ".d"> {
4495     let Inst{31} = 1;
4496     let Inst{22} = 0;
4497   }
4499   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4500                                                asm, ".d"> {
4501     let Inst{31} = 1;
4502     let Inst{22} = 0;
4503   }
4506 //---
4507 // Floating point conversion
4508 //---
4510 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4511                        RegisterClass srcType, string asm, list<dag> pattern>
4512     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4513       Sched<[WriteFCvt]> {
4514   bits<5> Rd;
4515   bits<5> Rn;
4516   let Inst{31-24} = 0b00011110;
4517   let Inst{23-22} = type;
4518   let Inst{21-17} = 0b10001;
4519   let Inst{16-15} = opcode;
4520   let Inst{14-10} = 0b10000;
4521   let Inst{9-5}   = Rn;
4522   let Inst{4-0}   = Rd;
4525 multiclass FPConversion<string asm> {
4526   // Double-precision to Half-precision
4527   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4528                              [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4530   // Double-precision to Single-precision
4531   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4532                              [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4534   // Half-precision to Double-precision
4535   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4536                              [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4538   // Half-precision to Single-precision
4539   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4540                              [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4542   // Single-precision to Double-precision
4543   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4544                              [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4546   // Single-precision to Half-precision
4547   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4548                              [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4551 //---
4552 // Single operand floating point data processing
4553 //---
4555 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4556 class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4557                               ValueType vt, string asm, SDPatternOperator node>
4558     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4559          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4560       Sched<[WriteF]> {
4561   bits<5> Rd;
4562   bits<5> Rn;
4563   let Inst{31-24} = 0b00011110;
4564   let Inst{21}    = 0b1;
4565   let Inst{20-15} = opcode;
4566   let Inst{14-10} = 0b10000;
4567   let Inst{9-5}   = Rn;
4568   let Inst{4-0}   = Rd;
4571 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4572                                SDPatternOperator node = null_frag> {
4574   def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4575     let Inst{23-22} = 0b11; // 16-bit size flag
4576     let Predicates = [HasFullFP16];
4577   }
4579   def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4580     let Inst{23-22} = 0b00; // 32-bit size flag
4581   }
4583   def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4584     let Inst{23-22} = 0b01; // 64-bit size flag
4585   }
4588 multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4589                   SDPatternOperator node = null_frag>{
4591   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4592     let Inst{23-22} = 0b00; // 32-bit registers
4593   }
4595   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4596     let Inst{23-22} = 0b01; // 64-bit registers
4597   }
4600 // FRInt[32|64][Z|N] instructions
4601 multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4602       SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4604 //---
4605 // Two operand floating point data processing
4606 //---
4608 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4609 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4610                            string asm, list<dag> pat>
4611     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4612          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4613       Sched<[WriteF]> {
4614   bits<5> Rd;
4615   bits<5> Rn;
4616   bits<5> Rm;
4617   let Inst{31-24} = 0b00011110;
4618   let Inst{21}    = 1;
4619   let Inst{20-16} = Rm;
4620   let Inst{15-12} = opcode;
4621   let Inst{11-10} = 0b10;
4622   let Inst{9-5}   = Rn;
4623   let Inst{4-0}   = Rd;
4626 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4627                             SDPatternOperator node = null_frag> {
4628   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4629                          [(set (f16 FPR16:$Rd),
4630                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4631     let Inst{23-22} = 0b11; // 16-bit size flag
4632     let Predicates = [HasFullFP16];
4633   }
4635   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4636                          [(set (f32 FPR32:$Rd),
4637                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4638     let Inst{23-22} = 0b00; // 32-bit size flag
4639   }
4641   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4642                          [(set (f64 FPR64:$Rd),
4643                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4644     let Inst{23-22} = 0b01; // 64-bit size flag
4645   }
4648 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4649   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4650                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4651     let Inst{23-22} = 0b11; // 16-bit size flag
4652     let Predicates = [HasFullFP16];
4653   }
4655   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4656                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4657     let Inst{23-22} = 0b00; // 32-bit size flag
4658   }
4660   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4661                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4662     let Inst{23-22} = 0b01; // 64-bit size flag
4663   }
4667 //---
4668 // Three operand floating point data processing
4669 //---
4671 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4672                              RegisterClass regtype, string asm, list<dag> pat>
4673     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4674          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4675       Sched<[WriteFMul]> {
4676   bits<5> Rd;
4677   bits<5> Rn;
4678   bits<5> Rm;
4679   bits<5> Ra;
4680   let Inst{31-24} = 0b00011111;
4681   let Inst{21}    = isNegated;
4682   let Inst{20-16} = Rm;
4683   let Inst{15}    = isSub;
4684   let Inst{14-10} = Ra;
4685   let Inst{9-5}   = Rn;
4686   let Inst{4-0}   = Rd;
4689 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4690                               SDPatternOperator node> {
4691   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4692             [(set FPR16:$Rd,
4693                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4694     let Inst{23-22} = 0b11; // 16-bit size flag
4695     let Predicates = [HasFullFP16];
4696   }
4698   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4699             [(set FPR32:$Rd,
4700                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4701     let Inst{23-22} = 0b00; // 32-bit size flag
4702   }
4704   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4705             [(set FPR64:$Rd,
4706                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4707     let Inst{23-22} = 0b01; // 64-bit size flag
4708   }
4711 //---
4712 // Floating point data comparisons
4713 //---
4715 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4716 class BaseOneOperandFPComparison<bit signalAllNans,
4717                                  RegisterClass regtype, string asm,
4718                                  list<dag> pat>
4719     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4720       Sched<[WriteFCmp]> {
4721   bits<5> Rn;
4722   let Inst{31-24} = 0b00011110;
4723   let Inst{21}    = 1;
4725   let Inst{15-10} = 0b001000;
4726   let Inst{9-5}   = Rn;
4727   let Inst{4}     = signalAllNans;
4728   let Inst{3-0}   = 0b1000;
4730   // Rm should be 0b00000 canonically, but we need to accept any value.
4731   let PostEncoderMethod = "fixOneOperandFPComparison";
4734 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4735 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4736                                 string asm, list<dag> pat>
4737     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4738       Sched<[WriteFCmp]> {
4739   bits<5> Rm;
4740   bits<5> Rn;
4741   let Inst{31-24} = 0b00011110;
4742   let Inst{21}    = 1;
4743   let Inst{20-16} = Rm;
4744   let Inst{15-10} = 0b001000;
4745   let Inst{9-5}   = Rn;
4746   let Inst{4}     = signalAllNans;
4747   let Inst{3-0}   = 0b0000;
4750 multiclass FPComparison<bit signalAllNans, string asm,
4751                         SDPatternOperator OpNode = null_frag> {
4752   let Defs = [NZCV] in {
4753   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4754       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4755     let Inst{23-22} = 0b11;
4756     let Predicates = [HasFullFP16];
4757   }
4759   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4760       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4761     let Inst{23-22} = 0b11;
4762     let Predicates = [HasFullFP16];
4763   }
4765   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4766       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4767     let Inst{23-22} = 0b00;
4768   }
4770   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4771       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4772     let Inst{23-22} = 0b00;
4773   }
4775   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4776       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4777     let Inst{23-22} = 0b01;
4778   }
4780   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4781       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4782     let Inst{23-22} = 0b01;
4783   }
4784   } // Defs = [NZCV]
4787 //---
4788 // Floating point conditional comparisons
4789 //---
4791 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4792 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4793                            string mnemonic, list<dag> pat>
4794     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4795          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4796       Sched<[WriteFCmp]> {
4797   let Uses = [NZCV];
4798   let Defs = [NZCV];
4800   bits<5> Rn;
4801   bits<5> Rm;
4802   bits<4> nzcv;
4803   bits<4> cond;
4805   let Inst{31-24} = 0b00011110;
4806   let Inst{21}    = 1;
4807   let Inst{20-16} = Rm;
4808   let Inst{15-12} = cond;
4809   let Inst{11-10} = 0b01;
4810   let Inst{9-5}   = Rn;
4811   let Inst{4}     = signalAllNans;
4812   let Inst{3-0}   = nzcv;
4815 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4816                             SDPatternOperator OpNode = null_frag> {
4817   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
4818       [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4819                           (i32 imm:$cond), NZCV))]> {
4820     let Inst{23-22} = 0b11;
4821     let Predicates = [HasFullFP16];
4822   }
4824   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4825       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4826                           (i32 imm:$cond), NZCV))]> {
4827     let Inst{23-22} = 0b00;
4828   }
4830   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4831       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4832                           (i32 imm:$cond), NZCV))]> {
4833     let Inst{23-22} = 0b01;
4834   }
4837 //---
4838 // Floating point conditional select
4839 //---
4841 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4842     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4843          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4844          [(set regtype:$Rd,
4845                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4846                           (i32 imm:$cond), NZCV))]>,
4847       Sched<[WriteF]> {
4848   bits<5> Rd;
4849   bits<5> Rn;
4850   bits<5> Rm;
4851   bits<4> cond;
4853   let Inst{31-24} = 0b00011110;
4854   let Inst{21}    = 1;
4855   let Inst{20-16} = Rm;
4856   let Inst{15-12} = cond;
4857   let Inst{11-10} = 0b11;
4858   let Inst{9-5}   = Rn;
4859   let Inst{4-0}   = Rd;
4862 multiclass FPCondSelect<string asm> {
4863   let Uses = [NZCV] in {
4864   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4865     let Inst{23-22} = 0b11;
4866     let Predicates = [HasFullFP16];
4867   }
4869   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4870     let Inst{23-22} = 0b00;
4871   }
4873   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4874     let Inst{23-22} = 0b01;
4875   }
4876   } // Uses = [NZCV]
4879 //---
4880 // Floating move immediate
4881 //---
4883 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4884   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4885       [(set regtype:$Rd, fpimmtype:$imm)]>,
4886     Sched<[WriteFImm]> {
4887   bits<5> Rd;
4888   bits<8> imm;
4889   let Inst{31-24} = 0b00011110;
4890   let Inst{21}    = 1;
4891   let Inst{20-13} = imm;
4892   let Inst{12-5}  = 0b10000000;
4893   let Inst{4-0}   = Rd;
4896 multiclass FPMoveImmediate<string asm> {
4897   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4898     let Inst{23-22} = 0b11;
4899     let Predicates = [HasFullFP16];
4900   }
4902   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4903     let Inst{23-22} = 0b00;
4904   }
4906   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4907     let Inst{23-22} = 0b01;
4908   }
4910 } // end of 'let Predicates = [HasFPARMv8]'
4912 //----------------------------------------------------------------------------
4913 // AdvSIMD
4914 //----------------------------------------------------------------------------
4916 let Predicates = [HasNEON] in {
4918 //----------------------------------------------------------------------------
4919 // AdvSIMD three register vector instructions
4920 //----------------------------------------------------------------------------
4922 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4923 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4924                         RegisterOperand regtype, string asm, string kind,
4925                         list<dag> pattern>
4926   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4927       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4928       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4929     Sched<[WriteV]> {
4930   bits<5> Rd;
4931   bits<5> Rn;
4932   bits<5> Rm;
4933   let Inst{31}    = 0;
4934   let Inst{30}    = Q;
4935   let Inst{29}    = U;
4936   let Inst{28-24} = 0b01110;
4937   let Inst{23-21} = size;
4938   let Inst{20-16} = Rm;
4939   let Inst{15-11} = opcode;
4940   let Inst{10}    = 1;
4941   let Inst{9-5}   = Rn;
4942   let Inst{4-0}   = Rd;
4945 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4946 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4947                         RegisterOperand regtype, string asm, string kind,
4948                         list<dag> pattern>
4949   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4950       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4951       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4952     Sched<[WriteV]> {
4953   bits<5> Rd;
4954   bits<5> Rn;
4955   bits<5> Rm;
4956   let Inst{31}    = 0;
4957   let Inst{30}    = Q;
4958   let Inst{29}    = U;
4959   let Inst{28-24} = 0b01110;
4960   let Inst{23-21} = size;
4961   let Inst{20-16} = Rm;
4962   let Inst{15-11} = opcode;
4963   let Inst{10}    = 1;
4964   let Inst{9-5}   = Rn;
4965   let Inst{4-0}   = Rd;
4968 // All operand sizes distinguished in the encoding.
4969 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4970                                SDPatternOperator OpNode> {
4971   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4972                                       asm, ".8b",
4973          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4974   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4975                                       asm, ".16b",
4976          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4977   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4978                                       asm, ".4h",
4979          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4980   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4981                                       asm, ".8h",
4982          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4983   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4984                                       asm, ".2s",
4985          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4986   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4987                                       asm, ".4s",
4988          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4989   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4990                                       asm, ".2d",
4991          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4994 // As above, but D sized elements unsupported.
4995 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4996                                   SDPatternOperator OpNode> {
4997   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4998                                       asm, ".8b",
4999         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5000   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5001                                       asm, ".16b",
5002         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5003   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5004                                       asm, ".4h",
5005         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5006   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5007                                       asm, ".8h",
5008         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5009   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5010                                       asm, ".2s",
5011         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5012   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5013                                       asm, ".4s",
5014         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5017 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5018                                   SDPatternOperator OpNode> {
5019   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5020                                       asm, ".8b",
5021       [(set (v8i8 V64:$dst),
5022             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5023   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5024                                       asm, ".16b",
5025       [(set (v16i8 V128:$dst),
5026             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5027   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5028                                       asm, ".4h",
5029       [(set (v4i16 V64:$dst),
5030             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5031   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5032                                       asm, ".8h",
5033       [(set (v8i16 V128:$dst),
5034             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5035   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5036                                       asm, ".2s",
5037       [(set (v2i32 V64:$dst),
5038             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5039   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5040                                       asm, ".4s",
5041       [(set (v4i32 V128:$dst),
5042             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5045 // As above, but only B sized elements supported.
5046 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5047                                 SDPatternOperator OpNode> {
5048   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5049                                       asm, ".8b",
5050     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5051   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5052                                       asm, ".16b",
5053     [(set (v16i8 V128:$Rd),
5054           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5057 // As above, but only floating point elements supported.
5058 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5059                                  string asm, SDPatternOperator OpNode> {
5060   let Predicates = [HasNEON, HasFullFP16] in {
5061   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5062                                       asm, ".4h",
5063         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5064   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5065                                       asm, ".8h",
5066         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5067   } // Predicates = [HasNEON, HasFullFP16]
5068   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5069                                       asm, ".2s",
5070         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5071   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5072                                       asm, ".4s",
5073         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5074   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5075                                       asm, ".2d",
5076         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5079 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5080                                     string asm,
5081                                     SDPatternOperator OpNode> {
5082   let Predicates = [HasNEON, HasFullFP16] in {
5083   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5084                                       asm, ".4h",
5085         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5086   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5087                                       asm, ".8h",
5088         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5089   } // Predicates = [HasNEON, HasFullFP16]
5090   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5091                                       asm, ".2s",
5092         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5093   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5094                                       asm, ".4s",
5095         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5096   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5097                                       asm, ".2d",
5098         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5101 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5102                                  string asm, SDPatternOperator OpNode> {
5103   let Predicates = [HasNEON, HasFullFP16] in {
5104   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5105                                       asm, ".4h",
5106      [(set (v4f16 V64:$dst),
5107            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5108   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5109                                       asm, ".8h",
5110      [(set (v8f16 V128:$dst),
5111            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5112   } // Predicates = [HasNEON, HasFullFP16]
5113   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5114                                       asm, ".2s",
5115      [(set (v2f32 V64:$dst),
5116            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5117   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5118                                       asm, ".4s",
5119      [(set (v4f32 V128:$dst),
5120            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5121   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5122                                       asm, ".2d",
5123      [(set (v2f64 V128:$dst),
5124            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5127 // As above, but D and B sized elements unsupported.
5128 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5129                                 SDPatternOperator OpNode> {
5130   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5131                                       asm, ".4h",
5132         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5133   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5134                                       asm, ".8h",
5135         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5136   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5137                                       asm, ".2s",
5138         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5139   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5140                                       asm, ".4s",
5141         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5144 // Logical three vector ops share opcode bits, and only use B sized elements.
5145 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5146                                   SDPatternOperator OpNode = null_frag> {
5147   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5148                                      asm, ".8b",
5149                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5150   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5151                                      asm, ".16b",
5152                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5154   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5155           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5156   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5157           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5158   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5159           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5161   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5162       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5163   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5164       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5165   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5166       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5169 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5170                                   string asm, SDPatternOperator OpNode> {
5171   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5172                                      asm, ".8b",
5173              [(set (v8i8 V64:$dst),
5174                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5175   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5176                                      asm, ".16b",
5177              [(set (v16i8 V128:$dst),
5178                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5179                            (v16i8 V128:$Rm)))]>;
5181   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5182                            (v4i16 V64:$RHS))),
5183           (!cast<Instruction>(NAME#"v8i8")
5184             V64:$LHS, V64:$MHS, V64:$RHS)>;
5185   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5186                            (v2i32 V64:$RHS))),
5187           (!cast<Instruction>(NAME#"v8i8")
5188             V64:$LHS, V64:$MHS, V64:$RHS)>;
5189   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5190                            (v1i64 V64:$RHS))),
5191           (!cast<Instruction>(NAME#"v8i8")
5192             V64:$LHS, V64:$MHS, V64:$RHS)>;
5194   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5195                            (v8i16 V128:$RHS))),
5196       (!cast<Instruction>(NAME#"v16i8")
5197         V128:$LHS, V128:$MHS, V128:$RHS)>;
5198   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5199                            (v4i32 V128:$RHS))),
5200       (!cast<Instruction>(NAME#"v16i8")
5201         V128:$LHS, V128:$MHS, V128:$RHS)>;
5202   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5203                            (v2i64 V128:$RHS))),
5204       (!cast<Instruction>(NAME#"v16i8")
5205         V128:$LHS, V128:$MHS, V128:$RHS)>;
5208 // ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5209 // bytes from S-sized elements.
5210 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
5211                                  string kind2, RegisterOperand RegType,
5212                                  ValueType AccumType, ValueType InputType,
5213                                  SDPatternOperator OpNode> :
5214         BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
5215         [(set (AccumType RegType:$dst),
5216               (OpNode (AccumType RegType:$Rd),
5217                       (InputType RegType:$Rn),
5218                       (InputType RegType:$Rm)))]> {
5219   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5222 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
5223   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
5224                                          v2i32, v8i8, OpNode>;
5225   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
5226                                          v4i32, v16i8, OpNode>;
5229 // ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5230 // select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5231 // 8H to 4S, when Q=1).
5232 class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5233                                  string kind2, RegisterOperand RegType,
5234                                  ValueType AccumType, ValueType InputType,
5235                                  SDPatternOperator OpNode> :
5236         BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5237                 [(set (AccumType RegType:$dst),
5238               (OpNode (AccumType RegType:$Rd),
5239                       (InputType RegType:$Rn),
5240                       (InputType RegType:$Rm)))]> {
5241   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5242   let Inst{13} = b13;
5245 multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5246                                   SDPatternOperator OpNode> {
5247   def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5248                                          v2f32, v4f16, OpNode>;
5249   def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5250                                          v4f32, v8f16, OpNode>;
5254 //----------------------------------------------------------------------------
5255 // AdvSIMD two register vector instructions.
5256 //----------------------------------------------------------------------------
5258 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5259 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5260                             bits<2> size2, RegisterOperand regtype, string asm,
5261                             string dstkind, string srckind, list<dag> pattern>
5262   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5263       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5264       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5265     Sched<[WriteV]> {
5266   bits<5> Rd;
5267   bits<5> Rn;
5268   let Inst{31}    = 0;
5269   let Inst{30}    = Q;
5270   let Inst{29}    = U;
5271   let Inst{28-24} = 0b01110;
5272   let Inst{23-22} = size;
5273   let Inst{21} = 0b1;
5274   let Inst{20-19} = size2;
5275   let Inst{18-17} = 0b00;
5276   let Inst{16-12} = opcode;
5277   let Inst{11-10} = 0b10;
5278   let Inst{9-5}   = Rn;
5279   let Inst{4-0}   = Rd;
5282 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5283 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5284                                 bits<2> size2, RegisterOperand regtype,
5285                                 string asm, string dstkind, string srckind,
5286                                 list<dag> pattern>
5287   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5288       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5289       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5290     Sched<[WriteV]> {
5291   bits<5> Rd;
5292   bits<5> Rn;
5293   let Inst{31}    = 0;
5294   let Inst{30}    = Q;
5295   let Inst{29}    = U;
5296   let Inst{28-24} = 0b01110;
5297   let Inst{23-22} = size;
5298   let Inst{21} = 0b1;
5299   let Inst{20-19} = size2;
5300   let Inst{18-17} = 0b00;
5301   let Inst{16-12} = opcode;
5302   let Inst{11-10} = 0b10;
5303   let Inst{9-5}   = Rn;
5304   let Inst{4-0}   = Rd;
5307 // Supports B, H, and S element sizes.
5308 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5309                             SDPatternOperator OpNode> {
5310   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5311                                       asm, ".8b", ".8b",
5312                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5313   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5314                                       asm, ".16b", ".16b",
5315                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5316   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5317                                       asm, ".4h", ".4h",
5318                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5319   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5320                                       asm, ".8h", ".8h",
5321                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5322   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5323                                       asm, ".2s", ".2s",
5324                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5325   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5326                                       asm, ".4s", ".4s",
5327                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5330 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5331                             RegisterOperand regtype, string asm, string dstkind,
5332                             string srckind, string amount>
5333   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5334       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5335       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5336     Sched<[WriteV]> {
5337   bits<5> Rd;
5338   bits<5> Rn;
5339   let Inst{31}    = 0;
5340   let Inst{30}    = Q;
5341   let Inst{29-24} = 0b101110;
5342   let Inst{23-22} = size;
5343   let Inst{21-10} = 0b100001001110;
5344   let Inst{9-5}   = Rn;
5345   let Inst{4-0}   = Rd;
5348 multiclass SIMDVectorLShiftLongBySizeBHS {
5349   let hasSideEffects = 0 in {
5350   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5351                                              "shll", ".8h",  ".8b", "8">;
5352   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5353                                              "shll2", ".8h", ".16b", "8">;
5354   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5355                                              "shll", ".4s",  ".4h", "16">;
5356   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5357                                              "shll2", ".4s", ".8h", "16">;
5358   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5359                                              "shll", ".2d",  ".2s", "32">;
5360   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5361                                              "shll2", ".2d", ".4s", "32">;
5362   }
5365 // Supports all element sizes.
5366 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5367                              SDPatternOperator OpNode> {
5368   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5369                                       asm, ".4h", ".8b",
5370                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5371   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5372                                       asm, ".8h", ".16b",
5373                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5374   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5375                                       asm, ".2s", ".4h",
5376                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5377   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5378                                       asm, ".4s", ".8h",
5379                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5380   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5381                                       asm, ".1d", ".2s",
5382                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5383   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5384                                       asm, ".2d", ".4s",
5385                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5388 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5389                                  SDPatternOperator OpNode> {
5390   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5391                                           asm, ".4h", ".8b",
5392       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5393                                       (v8i8 V64:$Rn)))]>;
5394   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5395                                           asm, ".8h", ".16b",
5396       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5397                                       (v16i8 V128:$Rn)))]>;
5398   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5399                                           asm, ".2s", ".4h",
5400       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5401                                       (v4i16 V64:$Rn)))]>;
5402   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5403                                           asm, ".4s", ".8h",
5404       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5405                                       (v8i16 V128:$Rn)))]>;
5406   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5407                                           asm, ".1d", ".2s",
5408       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5409                                       (v2i32 V64:$Rn)))]>;
5410   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5411                                           asm, ".2d", ".4s",
5412       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5413                                       (v4i32 V128:$Rn)))]>;
5416 // Supports all element sizes, except 1xD.
5417 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5418                                   SDPatternOperator OpNode> {
5419   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5420                                     asm, ".8b", ".8b",
5421     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5422   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5423                                     asm, ".16b", ".16b",
5424     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5425   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5426                                     asm, ".4h", ".4h",
5427     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5428   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5429                                     asm, ".8h", ".8h",
5430     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5431   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5432                                     asm, ".2s", ".2s",
5433     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5434   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5435                                     asm, ".4s", ".4s",
5436     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5437   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5438                                     asm, ".2d", ".2d",
5439     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5442 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5443                              SDPatternOperator OpNode = null_frag> {
5444   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5445                                 asm, ".8b", ".8b",
5446     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5447   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5448                                 asm, ".16b", ".16b",
5449     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5450   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5451                                 asm, ".4h", ".4h",
5452     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5453   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5454                                 asm, ".8h", ".8h",
5455     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5456   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5457                                 asm, ".2s", ".2s",
5458     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5459   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5460                                 asm, ".4s", ".4s",
5461     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5462   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5463                                 asm, ".2d", ".2d",
5464     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5468 // Supports only B element sizes.
5469 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5470                           SDPatternOperator OpNode> {
5471   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5472                                 asm, ".8b", ".8b",
5473                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5474   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5475                                 asm, ".16b", ".16b",
5476                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5480 // Supports only B and H element sizes.
5481 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5482                                 SDPatternOperator OpNode> {
5483   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5484                                 asm, ".8b", ".8b",
5485                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5486   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5487                                 asm, ".16b", ".16b",
5488                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5489   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5490                                 asm, ".4h", ".4h",
5491                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5492   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5493                                 asm, ".8h", ".8h",
5494                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5497 // Supports H, S and D element sizes, uses high bit of the size field
5498 // as an extra opcode bit.
5499 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5500                            SDPatternOperator OpNode> {
5501   let Predicates = [HasNEON, HasFullFP16] in {
5502   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5503                                 asm, ".4h", ".4h",
5504                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5505   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5506                                 asm, ".8h", ".8h",
5507                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5508   } // Predicates = [HasNEON, HasFullFP16]
5509   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5510                                 asm, ".2s", ".2s",
5511                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5512   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5513                                 asm, ".4s", ".4s",
5514                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5515   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5516                                 asm, ".2d", ".2d",
5517                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5520 // Supports only S and D element sizes
5521 multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5522                            SDPatternOperator OpNode = null_frag> {
5524   def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5525                                 asm, ".2s", ".2s",
5526                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5527   def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5528                                 asm, ".4s", ".4s",
5529                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5530   def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5531                                 asm, ".2d", ".2d",
5532                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5535 multiclass FRIntNNTVector<bit U, bit op, string asm,
5536                           SDPatternOperator OpNode = null_frag> :
5537            SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5539 // Supports only S element size.
5540 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5541                            SDPatternOperator OpNode> {
5542   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5543                                 asm, ".2s", ".2s",
5544                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5545   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5546                                 asm, ".4s", ".4s",
5547                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5551 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5552                            SDPatternOperator OpNode> {
5553   let Predicates = [HasNEON, HasFullFP16] in {
5554   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5555                                 asm, ".4h", ".4h",
5556                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5557   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5558                                 asm, ".8h", ".8h",
5559                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5560   } // Predicates = [HasNEON, HasFullFP16]
5561   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5562                                 asm, ".2s", ".2s",
5563                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5564   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5565                                 asm, ".4s", ".4s",
5566                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5567   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5568                                 asm, ".2d", ".2d",
5569                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5572 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5573                            SDPatternOperator OpNode> {
5574   let Predicates = [HasNEON, HasFullFP16] in {
5575   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5576                                 asm, ".4h", ".4h",
5577                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5578   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5579                                 asm, ".8h", ".8h",
5580                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5581   } // Predicates = [HasNEON, HasFullFP16]
5582   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5583                                 asm, ".2s", ".2s",
5584                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5585   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5586                                 asm, ".4s", ".4s",
5587                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5588   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5589                                 asm, ".2d", ".2d",
5590                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5594 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5595                            RegisterOperand inreg, RegisterOperand outreg,
5596                            string asm, string outkind, string inkind,
5597                            list<dag> pattern>
5598   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5599       "{\t$Rd" # outkind # ", $Rn" # inkind #
5600       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5601     Sched<[WriteV]> {
5602   bits<5> Rd;
5603   bits<5> Rn;
5604   let Inst{31}    = 0;
5605   let Inst{30}    = Q;
5606   let Inst{29}    = U;
5607   let Inst{28-24} = 0b01110;
5608   let Inst{23-22} = size;
5609   let Inst{21-17} = 0b10000;
5610   let Inst{16-12} = opcode;
5611   let Inst{11-10} = 0b10;
5612   let Inst{9-5}   = Rn;
5613   let Inst{4-0}   = Rd;
5616 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5617                            RegisterOperand inreg, RegisterOperand outreg,
5618                            string asm, string outkind, string inkind,
5619                            list<dag> pattern>
5620   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5621       "{\t$Rd" # outkind # ", $Rn" # inkind #
5622       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5623     Sched<[WriteV]> {
5624   bits<5> Rd;
5625   bits<5> Rn;
5626   let Inst{31}    = 0;
5627   let Inst{30}    = Q;
5628   let Inst{29}    = U;
5629   let Inst{28-24} = 0b01110;
5630   let Inst{23-22} = size;
5631   let Inst{21-17} = 0b10000;
5632   let Inst{16-12} = opcode;
5633   let Inst{11-10} = 0b10;
5634   let Inst{9-5}   = Rn;
5635   let Inst{4-0}   = Rd;
5638 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5639                               SDPatternOperator OpNode> {
5640   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5641                                       asm, ".8b", ".8h",
5642         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5643   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5644                                       asm#"2", ".16b", ".8h", []>;
5645   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5646                                       asm, ".4h", ".4s",
5647         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5648   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5649                                       asm#"2", ".8h", ".4s", []>;
5650   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5651                                       asm, ".2s", ".2d",
5652         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5653   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5654                                       asm#"2", ".4s", ".2d", []>;
5656   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5657             (!cast<Instruction>(NAME # "v16i8")
5658                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5659   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5660             (!cast<Instruction>(NAME # "v8i16")
5661                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5662   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5663             (!cast<Instruction>(NAME # "v4i32")
5664                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5667 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5668                            bits<5> opcode, RegisterOperand regtype, string asm,
5669                            string kind, string zero, ValueType dty,
5670                            ValueType sty, SDNode OpNode>
5671   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5672       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5673       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5674       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5675     Sched<[WriteV]> {
5676   bits<5> Rd;
5677   bits<5> Rn;
5678   let Inst{31}    = 0;
5679   let Inst{30}    = Q;
5680   let Inst{29}    = U;
5681   let Inst{28-24} = 0b01110;
5682   let Inst{23-22} = size;
5683   let Inst{21} = 0b1;
5684   let Inst{20-19} = size2;
5685   let Inst{18-17} = 0b00;
5686   let Inst{16-12} = opcode;
5687   let Inst{11-10} = 0b10;
5688   let Inst{9-5}   = Rn;
5689   let Inst{4-0}   = Rd;
5692 // Comparisons support all element sizes, except 1xD.
5693 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5694                             SDNode OpNode> {
5695   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5696                                      asm, ".8b", "0",
5697                                      v8i8, v8i8, OpNode>;
5698   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5699                                      asm, ".16b", "0",
5700                                      v16i8, v16i8, OpNode>;
5701   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5702                                      asm, ".4h", "0",
5703                                      v4i16, v4i16, OpNode>;
5704   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5705                                      asm, ".8h", "0",
5706                                      v8i16, v8i16, OpNode>;
5707   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5708                                      asm, ".2s", "0",
5709                                      v2i32, v2i32, OpNode>;
5710   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5711                                      asm, ".4s", "0",
5712                                      v4i32, v4i32, OpNode>;
5713   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5714                                      asm, ".2d", "0",
5715                                      v2i64, v2i64, OpNode>;
5718 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5719 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5720                               string asm, SDNode OpNode> {
5722   let Predicates = [HasNEON, HasFullFP16] in {
5723   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5724                                      asm, ".4h", "0.0",
5725                                      v4i16, v4f16, OpNode>;
5726   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5727                                      asm, ".8h", "0.0",
5728                                      v8i16, v8f16, OpNode>;
5729   } // Predicates = [HasNEON, HasFullFP16]
5730   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5731                                      asm, ".2s", "0.0",
5732                                      v2i32, v2f32, OpNode>;
5733   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5734                                      asm, ".4s", "0.0",
5735                                      v4i32, v4f32, OpNode>;
5736   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5737                                      asm, ".2d", "0.0",
5738                                      v2i64, v2f64, OpNode>;
5740   let Predicates = [HasNEON, HasFullFP16] in {
5741   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5742                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5743   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5744                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5745   }
5746   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5747                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5748   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5749                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5750   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5751                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5752   let Predicates = [HasNEON, HasFullFP16] in {
5753   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5754                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5755   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5756                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5757   }
5758   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5759                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5760   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5761                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5762   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5763                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5766 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5767 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5768                              RegisterOperand outtype, RegisterOperand intype,
5769                              string asm, string VdTy, string VnTy,
5770                              list<dag> pattern>
5771   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5772       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5773     Sched<[WriteV]> {
5774   bits<5> Rd;
5775   bits<5> Rn;
5776   let Inst{31}    = 0;
5777   let Inst{30}    = Q;
5778   let Inst{29}    = U;
5779   let Inst{28-24} = 0b01110;
5780   let Inst{23-22} = size;
5781   let Inst{21-17} = 0b10000;
5782   let Inst{16-12} = opcode;
5783   let Inst{11-10} = 0b10;
5784   let Inst{9-5}   = Rn;
5785   let Inst{4-0}   = Rd;
5788 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5789                              RegisterOperand outtype, RegisterOperand intype,
5790                              string asm, string VdTy, string VnTy,
5791                              list<dag> pattern>
5792   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5793       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5794     Sched<[WriteV]> {
5795   bits<5> Rd;
5796   bits<5> Rn;
5797   let Inst{31}    = 0;
5798   let Inst{30}    = Q;
5799   let Inst{29}    = U;
5800   let Inst{28-24} = 0b01110;
5801   let Inst{23-22} = size;
5802   let Inst{21-17} = 0b10000;
5803   let Inst{16-12} = opcode;
5804   let Inst{11-10} = 0b10;
5805   let Inst{9-5}   = Rn;
5806   let Inst{4-0}   = Rd;
5809 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5810   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5811                                     asm, ".4s", ".4h", []>;
5812   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5813                                     asm#"2", ".4s", ".8h", []>;
5814   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5815                                     asm, ".2d", ".2s", []>;
5816   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5817                                     asm#"2", ".2d", ".4s", []>;
5820 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5821   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5822                                     asm, ".4h", ".4s", []>;
5823   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5824                                     asm#"2", ".8h", ".4s", []>;
5825   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5826                                     asm, ".2s", ".2d", []>;
5827   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5828                                     asm#"2", ".4s", ".2d", []>;
5831 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5832                                      Intrinsic OpNode> {
5833   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5834                                      asm, ".2s", ".2d",
5835                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5836   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5837                                     asm#"2", ".4s", ".2d", []>;
5839   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5840             (!cast<Instruction>(NAME # "v4f32")
5841                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5844 //----------------------------------------------------------------------------
5845 // AdvSIMD three register different-size vector instructions.
5846 //----------------------------------------------------------------------------
5848 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5849 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5850                       RegisterOperand outtype, RegisterOperand intype1,
5851                       RegisterOperand intype2, string asm,
5852                       string outkind, string inkind1, string inkind2,
5853                       list<dag> pattern>
5854   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5855       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5856       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5857     Sched<[WriteV]> {
5858   bits<5> Rd;
5859   bits<5> Rn;
5860   bits<5> Rm;
5861   let Inst{31}    = 0;
5862   let Inst{30}    = size{0};
5863   let Inst{29}    = U;
5864   let Inst{28-24} = 0b01110;
5865   let Inst{23-22} = size{2-1};
5866   let Inst{21}    = 1;
5867   let Inst{20-16} = Rm;
5868   let Inst{15-12} = opcode;
5869   let Inst{11-10} = 0b00;
5870   let Inst{9-5}   = Rn;
5871   let Inst{4-0}   = Rd;
5874 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5875 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5876                       RegisterOperand outtype, RegisterOperand intype1,
5877                       RegisterOperand intype2, string asm,
5878                       string outkind, string inkind1, string inkind2,
5879                       list<dag> pattern>
5880   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5881       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5882       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5883     Sched<[WriteV]> {
5884   bits<5> Rd;
5885   bits<5> Rn;
5886   bits<5> Rm;
5887   let Inst{31}    = 0;
5888   let Inst{30}    = size{0};
5889   let Inst{29}    = U;
5890   let Inst{28-24} = 0b01110;
5891   let Inst{23-22} = size{2-1};
5892   let Inst{21}    = 1;
5893   let Inst{20-16} = Rm;
5894   let Inst{15-12} = opcode;
5895   let Inst{11-10} = 0b00;
5896   let Inst{9-5}   = Rn;
5897   let Inst{4-0}   = Rd;
5900 // FIXME: TableGen doesn't know how to deal with expanded types that also
5901 //        change the element count (in this case, placing the results in
5902 //        the high elements of the result register rather than the low
5903 //        elements). Until that's fixed, we can't code-gen those.
5904 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5905                                     Intrinsic IntOp> {
5906   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5907                                                   V64, V128, V128,
5908                                                   asm, ".8b", ".8h", ".8h",
5909      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5910   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5911                                                   V128, V128, V128,
5912                                                   asm#"2", ".16b", ".8h", ".8h",
5913      []>;
5914   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5915                                                   V64, V128, V128,
5916                                                   asm, ".4h", ".4s", ".4s",
5917      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5918   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5919                                                   V128, V128, V128,
5920                                                   asm#"2", ".8h", ".4s", ".4s",
5921      []>;
5922   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5923                                                   V64, V128, V128,
5924                                                   asm, ".2s", ".2d", ".2d",
5925      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5926   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5927                                                   V128, V128, V128,
5928                                                   asm#"2", ".4s", ".2d", ".2d",
5929      []>;
5932   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5933   // a version attached to an instruction.
5934   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5935                                                    (v8i16 V128:$Rm))),
5936             (!cast<Instruction>(NAME # "v8i16_v16i8")
5937                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5938                 V128:$Rn, V128:$Rm)>;
5939   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5940                                                     (v4i32 V128:$Rm))),
5941             (!cast<Instruction>(NAME # "v4i32_v8i16")
5942                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5943                 V128:$Rn, V128:$Rm)>;
5944   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5945                                                     (v2i64 V128:$Rm))),
5946             (!cast<Instruction>(NAME # "v2i64_v4i32")
5947                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5948                 V128:$Rn, V128:$Rm)>;
5951 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5952                                       Intrinsic IntOp> {
5953   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5954                                             V128, V64, V64,
5955                                             asm, ".8h", ".8b", ".8b",
5956       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5957   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5958                                             V128, V128, V128,
5959                                             asm#"2", ".8h", ".16b", ".16b", []>;
5960   let Predicates = [HasAES] in {
5961     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5962                                               V128, V64, V64,
5963                                               asm, ".1q", ".1d", ".1d", []>;
5964     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5965                                               V128, V128, V128,
5966                                               asm#"2", ".1q", ".2d", ".2d", []>;
5967   }
5969   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5970                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5971       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5974 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5975                                  SDPatternOperator OpNode> {
5976   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5977                                                   V128, V64, V64,
5978                                                   asm, ".4s", ".4h", ".4h",
5979       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5980   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5981                                                   V128, V128, V128,
5982                                                   asm#"2", ".4s", ".8h", ".8h",
5983       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5984                                       (extract_high_v8i16 V128:$Rm)))]>;
5985   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5986                                                   V128, V64, V64,
5987                                                   asm, ".2d", ".2s", ".2s",
5988       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5989   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5990                                                   V128, V128, V128,
5991                                                   asm#"2", ".2d", ".4s", ".4s",
5992       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5993                                       (extract_high_v4i32 V128:$Rm)))]>;
5996 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5997                                   SDPatternOperator OpNode = null_frag> {
5998   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5999                                                   V128, V64, V64,
6000                                                   asm, ".8h", ".8b", ".8b",
6001       [(set (v8i16 V128:$Rd),
6002             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6003   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6004                                                  V128, V128, V128,
6005                                                  asm#"2", ".8h", ".16b", ".16b",
6006       [(set (v8i16 V128:$Rd),
6007             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6008                                 (extract_high_v16i8 V128:$Rm)))))]>;
6009   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6010                                                   V128, V64, V64,
6011                                                   asm, ".4s", ".4h", ".4h",
6012       [(set (v4i32 V128:$Rd),
6013             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6014   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6015                                                   V128, V128, V128,
6016                                                   asm#"2", ".4s", ".8h", ".8h",
6017       [(set (v4i32 V128:$Rd),
6018             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6019                                   (extract_high_v8i16 V128:$Rm)))))]>;
6020   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6021                                                   V128, V64, V64,
6022                                                   asm, ".2d", ".2s", ".2s",
6023       [(set (v2i64 V128:$Rd),
6024             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6025   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6026                                                   V128, V128, V128,
6027                                                   asm#"2", ".2d", ".4s", ".4s",
6028       [(set (v2i64 V128:$Rd),
6029             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6030                                  (extract_high_v4i32 V128:$Rm)))))]>;
6033 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6034                                           string asm,
6035                                           SDPatternOperator OpNode> {
6036   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6037                                                   V128, V64, V64,
6038                                                   asm, ".8h", ".8b", ".8b",
6039     [(set (v8i16 V128:$dst),
6040           (add (v8i16 V128:$Rd),
6041                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6042   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6043                                                  V128, V128, V128,
6044                                                  asm#"2", ".8h", ".16b", ".16b",
6045     [(set (v8i16 V128:$dst),
6046           (add (v8i16 V128:$Rd),
6047                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6048                                    (extract_high_v16i8 V128:$Rm))))))]>;
6049   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6050                                                   V128, V64, V64,
6051                                                   asm, ".4s", ".4h", ".4h",
6052     [(set (v4i32 V128:$dst),
6053           (add (v4i32 V128:$Rd),
6054                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6055   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6056                                                   V128, V128, V128,
6057                                                   asm#"2", ".4s", ".8h", ".8h",
6058     [(set (v4i32 V128:$dst),
6059           (add (v4i32 V128:$Rd),
6060                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6061                                     (extract_high_v8i16 V128:$Rm))))))]>;
6062   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6063                                                   V128, V64, V64,
6064                                                   asm, ".2d", ".2s", ".2s",
6065     [(set (v2i64 V128:$dst),
6066           (add (v2i64 V128:$Rd),
6067                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6068   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6069                                                   V128, V128, V128,
6070                                                   asm#"2", ".2d", ".4s", ".4s",
6071     [(set (v2i64 V128:$dst),
6072           (add (v2i64 V128:$Rd),
6073                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6074                                     (extract_high_v4i32 V128:$Rm))))))]>;
6077 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6078                                   SDPatternOperator OpNode = null_frag> {
6079   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6080                                                   V128, V64, V64,
6081                                                   asm, ".8h", ".8b", ".8b",
6082       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6083   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6084                                                  V128, V128, V128,
6085                                                  asm#"2", ".8h", ".16b", ".16b",
6086       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6087                                       (extract_high_v16i8 V128:$Rm)))]>;
6088   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6089                                                   V128, V64, V64,
6090                                                   asm, ".4s", ".4h", ".4h",
6091       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6092   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6093                                                   V128, V128, V128,
6094                                                   asm#"2", ".4s", ".8h", ".8h",
6095       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6096                                       (extract_high_v8i16 V128:$Rm)))]>;
6097   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6098                                                   V128, V64, V64,
6099                                                   asm, ".2d", ".2s", ".2s",
6100       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6101   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6102                                                   V128, V128, V128,
6103                                                   asm#"2", ".2d", ".4s", ".4s",
6104       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6105                                       (extract_high_v4i32 V128:$Rm)))]>;
6108 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6109                                       string asm,
6110                                       SDPatternOperator OpNode> {
6111   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6112                                                   V128, V64, V64,
6113                                                   asm, ".8h", ".8b", ".8b",
6114     [(set (v8i16 V128:$dst),
6115           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6116   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6117                                                  V128, V128, V128,
6118                                                  asm#"2", ".8h", ".16b", ".16b",
6119     [(set (v8i16 V128:$dst),
6120           (OpNode (v8i16 V128:$Rd),
6121                   (extract_high_v16i8 V128:$Rn),
6122                   (extract_high_v16i8 V128:$Rm)))]>;
6123   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6124                                                   V128, V64, V64,
6125                                                   asm, ".4s", ".4h", ".4h",
6126     [(set (v4i32 V128:$dst),
6127           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6128   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6129                                                   V128, V128, V128,
6130                                                   asm#"2", ".4s", ".8h", ".8h",
6131     [(set (v4i32 V128:$dst),
6132           (OpNode (v4i32 V128:$Rd),
6133                   (extract_high_v8i16 V128:$Rn),
6134                   (extract_high_v8i16 V128:$Rm)))]>;
6135   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6136                                                   V128, V64, V64,
6137                                                   asm, ".2d", ".2s", ".2s",
6138     [(set (v2i64 V128:$dst),
6139           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6140   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6141                                                   V128, V128, V128,
6142                                                   asm#"2", ".2d", ".4s", ".4s",
6143     [(set (v2i64 V128:$dst),
6144           (OpNode (v2i64 V128:$Rd),
6145                   (extract_high_v4i32 V128:$Rn),
6146                   (extract_high_v4i32 V128:$Rm)))]>;
6149 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6150                                            SDPatternOperator Accum> {
6151   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6152                                                   V128, V64, V64,
6153                                                   asm, ".4s", ".4h", ".4h",
6154     [(set (v4i32 V128:$dst),
6155           (Accum (v4i32 V128:$Rd),
6156                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6157                                                 (v4i16 V64:$Rm)))))]>;
6158   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6159                                                   V128, V128, V128,
6160                                                   asm#"2", ".4s", ".8h", ".8h",
6161     [(set (v4i32 V128:$dst),
6162           (Accum (v4i32 V128:$Rd),
6163                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6164                                             (extract_high_v8i16 V128:$Rm)))))]>;
6165   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6166                                                   V128, V64, V64,
6167                                                   asm, ".2d", ".2s", ".2s",
6168     [(set (v2i64 V128:$dst),
6169           (Accum (v2i64 V128:$Rd),
6170                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6171                                                 (v2i32 V64:$Rm)))))]>;
6172   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6173                                                   V128, V128, V128,
6174                                                   asm#"2", ".2d", ".4s", ".4s",
6175     [(set (v2i64 V128:$dst),
6176           (Accum (v2i64 V128:$Rd),
6177                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6178                                             (extract_high_v4i32 V128:$Rm)))))]>;
6181 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6182                                   SDPatternOperator OpNode> {
6183   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6184                                                   V128, V128, V64,
6185                                                   asm, ".8h", ".8h", ".8b",
6186        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6187   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6188                                                   V128, V128, V128,
6189                                                   asm#"2", ".8h", ".8h", ".16b",
6190        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6191                                        (extract_high_v16i8 V128:$Rm)))]>;
6192   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6193                                                   V128, V128, V64,
6194                                                   asm, ".4s", ".4s", ".4h",
6195        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6196   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6197                                                   V128, V128, V128,
6198                                                   asm#"2", ".4s", ".4s", ".8h",
6199        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6200                                        (extract_high_v8i16 V128:$Rm)))]>;
6201   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6202                                                   V128, V128, V64,
6203                                                   asm, ".2d", ".2d", ".2s",
6204        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6205   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6206                                                   V128, V128, V128,
6207                                                   asm#"2", ".2d", ".2d", ".4s",
6208        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6209                                        (extract_high_v4i32 V128:$Rm)))]>;
6212 //----------------------------------------------------------------------------
6213 // AdvSIMD bitwise extract from vector
6214 //----------------------------------------------------------------------------
6216 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6217                              string asm, string kind>
6218   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6219       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6220       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6221       [(set (vty regtype:$Rd),
6222             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6223     Sched<[WriteV]> {
6224   bits<5> Rd;
6225   bits<5> Rn;
6226   bits<5> Rm;
6227   bits<4> imm;
6228   let Inst{31}    = 0;
6229   let Inst{30}    = size;
6230   let Inst{29-21} = 0b101110000;
6231   let Inst{20-16} = Rm;
6232   let Inst{15}    = 0;
6233   let Inst{14-11} = imm;
6234   let Inst{10}    = 0;
6235   let Inst{9-5}   = Rn;
6236   let Inst{4-0}   = Rd;
6240 multiclass SIMDBitwiseExtract<string asm> {
6241   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6242     let imm{3} = 0;
6243   }
6244   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6247 //----------------------------------------------------------------------------
6248 // AdvSIMD zip vector
6249 //----------------------------------------------------------------------------
6251 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6252                         string asm, string kind, SDNode OpNode, ValueType valty>
6253   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6254       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6255       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6256       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6257     Sched<[WriteV]> {
6258   bits<5> Rd;
6259   bits<5> Rn;
6260   bits<5> Rm;
6261   let Inst{31}    = 0;
6262   let Inst{30}    = size{0};
6263   let Inst{29-24} = 0b001110;
6264   let Inst{23-22} = size{2-1};
6265   let Inst{21}    = 0;
6266   let Inst{20-16} = Rm;
6267   let Inst{15}    = 0;
6268   let Inst{14-12} = opc;
6269   let Inst{11-10} = 0b10;
6270   let Inst{9-5}   = Rn;
6271   let Inst{4-0}   = Rd;
6274 multiclass SIMDZipVector<bits<3>opc, string asm,
6275                          SDNode OpNode> {
6276   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6277       asm, ".8b", OpNode, v8i8>;
6278   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6279       asm, ".16b", OpNode, v16i8>;
6280   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6281       asm, ".4h", OpNode, v4i16>;
6282   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6283       asm, ".8h", OpNode, v8i16>;
6284   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6285       asm, ".2s", OpNode, v2i32>;
6286   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6287       asm, ".4s", OpNode, v4i32>;
6288   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6289       asm, ".2d", OpNode, v2i64>;
6291   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6292         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6293   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6294         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6295   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6296         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6297   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6298         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6299   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6300         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6303 //----------------------------------------------------------------------------
6304 // AdvSIMD three register scalar instructions
6305 //----------------------------------------------------------------------------
6307 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6308 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6309                         RegisterClass regtype, string asm,
6310                         list<dag> pattern>
6311   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6312       "\t$Rd, $Rn, $Rm", "", pattern>,
6313     Sched<[WriteV]> {
6314   bits<5> Rd;
6315   bits<5> Rn;
6316   bits<5> Rm;
6317   let Inst{31-30} = 0b01;
6318   let Inst{29}    = U;
6319   let Inst{28-24} = 0b11110;
6320   let Inst{23-21} = size;
6321   let Inst{20-16} = Rm;
6322   let Inst{15-11} = opcode;
6323   let Inst{10}    = 1;
6324   let Inst{9-5}   = Rn;
6325   let Inst{4-0}   = Rd;
6328 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6329 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6330                         dag oops, dag iops, string asm,
6331             list<dag> pattern>
6332   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6333     Sched<[WriteV]> {
6334   bits<5> Rd;
6335   bits<5> Rn;
6336   bits<5> Rm;
6337   let Inst{31-30} = 0b01;
6338   let Inst{29}    = U;
6339   let Inst{28-24} = 0b11110;
6340   let Inst{23-22} = size;
6341   let Inst{21}    = R;
6342   let Inst{20-16} = Rm;
6343   let Inst{15-11} = opcode;
6344   let Inst{10}    = 1;
6345   let Inst{9-5}   = Rn;
6346   let Inst{4-0}   = Rd;
6349 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6350                             SDPatternOperator OpNode> {
6351   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6352     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6355 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6356                                SDPatternOperator OpNode> {
6357   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6358     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6359   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6360   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6361   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6363   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6364             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6365   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6366             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6369 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6370                              SDPatternOperator OpNode> {
6371   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6372                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6373   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6376 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6377                                  SDPatternOperator OpNode = null_frag> {
6378   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6379                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6380                                      asm, []>;
6381   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6382                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6383                                      asm, []>;
6386 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6387                              SDPatternOperator OpNode = null_frag> {
6388   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6389     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6390       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6391     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6392       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6393     let Predicates = [HasNEON, HasFullFP16] in {
6394     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6395       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6396     } // Predicates = [HasNEON, HasFullFP16]
6397   }
6399   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6400             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6403 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6404                                 SDPatternOperator OpNode = null_frag> {
6405   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6406     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6407       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6408     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6409       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6410     let Predicates = [HasNEON, HasFullFP16] in {
6411     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6412       []>;
6413     } // Predicates = [HasNEON, HasFullFP16]
6414   }
6416   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6417             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6420 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6421               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6422   : I<oops, iops, asm,
6423       "\t$Rd, $Rn, $Rm", cstr, pat>,
6424     Sched<[WriteV]> {
6425   bits<5> Rd;
6426   bits<5> Rn;
6427   bits<5> Rm;
6428   let Inst{31-30} = 0b01;
6429   let Inst{29}    = U;
6430   let Inst{28-24} = 0b11110;
6431   let Inst{23-22} = size;
6432   let Inst{21}    = 1;
6433   let Inst{20-16} = Rm;
6434   let Inst{15-11} = opcode;
6435   let Inst{10}    = 0;
6436   let Inst{9-5}   = Rn;
6437   let Inst{4-0}   = Rd;
6440 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6441 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6442                                   SDPatternOperator OpNode = null_frag> {
6443   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6444                                       (outs FPR32:$Rd),
6445                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6446   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6447                                       (outs FPR64:$Rd),
6448                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6449             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6452 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6453 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6454                                   SDPatternOperator OpNode = null_frag> {
6455   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6456                                       (outs FPR32:$dst),
6457                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6458                                       asm, "$Rd = $dst", []>;
6459   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6460                                       (outs FPR64:$dst),
6461                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6462                                       asm, "$Rd = $dst",
6463             [(set (i64 FPR64:$dst),
6464                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6467 //----------------------------------------------------------------------------
6468 // AdvSIMD two register scalar instructions
6469 //----------------------------------------------------------------------------
6471 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6472 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6473                         RegisterClass regtype, RegisterClass regtype2,
6474                         string asm, list<dag> pat>
6475   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6476       "\t$Rd, $Rn", "", pat>,
6477     Sched<[WriteV]> {
6478   bits<5> Rd;
6479   bits<5> Rn;
6480   let Inst{31-30} = 0b01;
6481   let Inst{29}    = U;
6482   let Inst{28-24} = 0b11110;
6483   let Inst{23-22} = size;
6484   let Inst{21} = 0b1;
6485   let Inst{20-19} = size2;
6486   let Inst{18-17} = 0b00;
6487   let Inst{16-12} = opcode;
6488   let Inst{11-10} = 0b10;
6489   let Inst{9-5}   = Rn;
6490   let Inst{4-0}   = Rd;
6493 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6494 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6495                         RegisterClass regtype, RegisterClass regtype2,
6496                         string asm, list<dag> pat>
6497   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6498       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6499     Sched<[WriteV]> {
6500   bits<5> Rd;
6501   bits<5> Rn;
6502   let Inst{31-30} = 0b01;
6503   let Inst{29}    = U;
6504   let Inst{28-24} = 0b11110;
6505   let Inst{23-22} = size;
6506   let Inst{21-17} = 0b10000;
6507   let Inst{16-12} = opcode;
6508   let Inst{11-10} = 0b10;
6509   let Inst{9-5}   = Rn;
6510   let Inst{4-0}   = Rd;
6514 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6515 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6516                         RegisterClass regtype, string asm, string zero>
6517   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6518       "\t$Rd, $Rn, #" # zero, "", []>,
6519     Sched<[WriteV]> {
6520   bits<5> Rd;
6521   bits<5> Rn;
6522   let Inst{31-30} = 0b01;
6523   let Inst{29}    = U;
6524   let Inst{28-24} = 0b11110;
6525   let Inst{23-22} = size;
6526   let Inst{21} = 0b1;
6527   let Inst{20-19} = size2;
6528   let Inst{18-17} = 0b00;
6529   let Inst{16-12} = opcode;
6530   let Inst{11-10} = 0b10;
6531   let Inst{9-5}   = Rn;
6532   let Inst{4-0}   = Rd;
6535 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6536   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6537      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6538     Sched<[WriteV]> {
6539   bits<5> Rd;
6540   bits<5> Rn;
6541   let Inst{31-17} = 0b011111100110000;
6542   let Inst{16-12} = opcode;
6543   let Inst{11-10} = 0b10;
6544   let Inst{9-5}   = Rn;
6545   let Inst{4-0}   = Rd;
6548 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6549                              SDPatternOperator OpNode> {
6550   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6552   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6553             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6556 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6557                               SDPatternOperator OpNode> {
6558   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6559   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6560   let Predicates = [HasNEON, HasFullFP16] in {
6561   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6562   }
6564   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6565                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6566   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6567                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6568   let Predicates = [HasNEON, HasFullFP16] in {
6569   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6570                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6571   }
6573   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6574             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6577 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6578                           SDPatternOperator OpNode = null_frag> {
6579   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6580     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6582   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6583             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6586 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6587   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6588   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6589   let Predicates = [HasNEON, HasFullFP16] in {
6590   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6591   }
6594 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6595                               SDPatternOperator OpNode> {
6596   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6597                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6598   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6599                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6600   let Predicates = [HasNEON, HasFullFP16] in {
6601   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6602                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6603   }
6606 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6607                              SDPatternOperator OpNode = null_frag> {
6608   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6609     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6610            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6611     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6612            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6613     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6614     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6615   }
6617   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6618             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6621 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6622                                  Intrinsic OpNode> {
6623   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6624     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6625         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6626     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6627         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6628     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6629     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6630   }
6632   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6633             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6638 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6639 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6640                                  SDPatternOperator OpNode = null_frag> {
6641   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6642         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6643   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6644   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6647 //----------------------------------------------------------------------------
6648 // AdvSIMD scalar pairwise instructions
6649 //----------------------------------------------------------------------------
6651 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6652 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6653                         RegisterOperand regtype, RegisterOperand vectype,
6654                         string asm, string kind>
6655   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6656       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6657     Sched<[WriteV]> {
6658   bits<5> Rd;
6659   bits<5> Rn;
6660   let Inst{31-30} = 0b01;
6661   let Inst{29}    = U;
6662   let Inst{28-24} = 0b11110;
6663   let Inst{23-22} = size;
6664   let Inst{21-17} = 0b11000;
6665   let Inst{16-12} = opcode;
6666   let Inst{11-10} = 0b10;
6667   let Inst{9-5}   = Rn;
6668   let Inst{4-0}   = Rd;
6671 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6672   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6673                                       asm, ".2d">;
6676 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6677   let Predicates = [HasNEON, HasFullFP16] in {
6678   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6679                                       asm, ".2h">;
6680   }
6681   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6682                                       asm, ".2s">;
6683   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6684                                       asm, ".2d">;
6687 //----------------------------------------------------------------------------
6688 // AdvSIMD across lanes instructions
6689 //----------------------------------------------------------------------------
6691 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6692 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6693                           RegisterClass regtype, RegisterOperand vectype,
6694                           string asm, string kind, list<dag> pattern>
6695   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6696       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6697     Sched<[WriteV]> {
6698   bits<5> Rd;
6699   bits<5> Rn;
6700   let Inst{31}    = 0;
6701   let Inst{30}    = Q;
6702   let Inst{29}    = U;
6703   let Inst{28-24} = 0b01110;
6704   let Inst{23-22} = size;
6705   let Inst{21-17} = 0b11000;
6706   let Inst{16-12} = opcode;
6707   let Inst{11-10} = 0b10;
6708   let Inst{9-5}   = Rn;
6709   let Inst{4-0}   = Rd;
6712 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6713                               string asm> {
6714   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6715                                    asm, ".8b", []>;
6716   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6717                                    asm, ".16b", []>;
6718   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6719                                    asm, ".4h", []>;
6720   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6721                                    asm, ".8h", []>;
6722   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6723                                    asm, ".4s", []>;
6726 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6727   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6728                                    asm, ".8b", []>;
6729   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6730                                    asm, ".16b", []>;
6731   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6732                                    asm, ".4h", []>;
6733   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6734                                    asm, ".8h", []>;
6735   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6736                                    asm, ".4s", []>;
6739 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6740                             Intrinsic intOp> {
6741   let Predicates = [HasNEON, HasFullFP16] in {
6742   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6743                                    asm, ".4h",
6744         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6745   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6746                                    asm, ".8h",
6747         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6748   } // Predicates = [HasNEON, HasFullFP16]
6749   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6750                                    asm, ".4s",
6751         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6754 //----------------------------------------------------------------------------
6755 // AdvSIMD INS/DUP instructions
6756 //----------------------------------------------------------------------------
6758 // FIXME: There has got to be a better way to factor these. ugh.
6760 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6761                      string operands, string constraints, list<dag> pattern>
6762   : I<outs, ins, asm, operands, constraints, pattern>,
6763     Sched<[WriteV]> {
6764   bits<5> Rd;
6765   bits<5> Rn;
6766   let Inst{31} = 0;
6767   let Inst{30} = Q;
6768   let Inst{29} = op;
6769   let Inst{28-21} = 0b01110000;
6770   let Inst{15} = 0;
6771   let Inst{10} = 1;
6772   let Inst{9-5} = Rn;
6773   let Inst{4-0} = Rd;
6776 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6777                       RegisterOperand vecreg, RegisterClass regtype>
6778   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6779                    "{\t$Rd" # size # ", $Rn" #
6780                    "|" # size # "\t$Rd, $Rn}", "",
6781                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6782   let Inst{20-16} = imm5;
6783   let Inst{14-11} = 0b0001;
6786 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6787                          ValueType vectype, ValueType insreg,
6788                          RegisterOperand vecreg, Operand idxtype,
6789                          ValueType elttype, SDNode OpNode>
6790   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6791                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6792                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6793                  [(set (vectype vecreg:$Rd),
6794                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6795   let Inst{14-11} = 0b0000;
6798 class SIMDDup64FromElement
6799   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6800                        VectorIndexD, i64, AArch64duplane64> {
6801   bits<1> idx;
6802   let Inst{20} = idx;
6803   let Inst{19-16} = 0b1000;
6806 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6807                            RegisterOperand vecreg>
6808   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6809                        VectorIndexS, i64, AArch64duplane32> {
6810   bits<2> idx;
6811   let Inst{20-19} = idx;
6812   let Inst{18-16} = 0b100;
6815 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6816                            RegisterOperand vecreg>
6817   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6818                        VectorIndexH, i64, AArch64duplane16> {
6819   bits<3> idx;
6820   let Inst{20-18} = idx;
6821   let Inst{17-16} = 0b10;
6824 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6825                           RegisterOperand vecreg>
6826   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6827                        VectorIndexB, i64, AArch64duplane8> {
6828   bits<4> idx;
6829   let Inst{20-17} = idx;
6830   let Inst{16} = 1;
6833 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6834                   Operand idxtype, string asm, list<dag> pattern>
6835   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6836                    "{\t$Rd, $Rn" # size # "$idx" #
6837                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6838   let Inst{14-11} = imm4;
6841 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6842                Operand idxtype>
6843   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6844 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6845                Operand idxtype>
6846   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6847       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6849 class SIMDMovAlias<string asm, string size, Instruction inst,
6850                    RegisterClass regtype, Operand idxtype>
6851     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6852                     "|" # size # "\t$dst, $src$idx}",
6853                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6855 multiclass SMov {
6856   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6857     bits<4> idx;
6858     let Inst{20-17} = idx;
6859     let Inst{16} = 1;
6860   }
6861   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6862     bits<4> idx;
6863     let Inst{20-17} = idx;
6864     let Inst{16} = 1;
6865   }
6866   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6867     bits<3> idx;
6868     let Inst{20-18} = idx;
6869     let Inst{17-16} = 0b10;
6870   }
6871   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6872     bits<3> idx;
6873     let Inst{20-18} = idx;
6874     let Inst{17-16} = 0b10;
6875   }
6876   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6877     bits<2> idx;
6878     let Inst{20-19} = idx;
6879     let Inst{18-16} = 0b100;
6880   }
6883 multiclass UMov {
6884   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6885     bits<4> idx;
6886     let Inst{20-17} = idx;
6887     let Inst{16} = 1;
6888   }
6889   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6890     bits<3> idx;
6891     let Inst{20-18} = idx;
6892     let Inst{17-16} = 0b10;
6893   }
6894   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6895     bits<2> idx;
6896     let Inst{20-19} = idx;
6897     let Inst{18-16} = 0b100;
6898   }
6899   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6900     bits<1> idx;
6901     let Inst{20} = idx;
6902     let Inst{19-16} = 0b1000;
6903   }
6904   def : SIMDMovAlias<"mov", ".s",
6905                      !cast<Instruction>(NAME#"vi32"),
6906                      GPR32, VectorIndexS>;
6907   def : SIMDMovAlias<"mov", ".d",
6908                      !cast<Instruction>(NAME#"vi64"),
6909                      GPR64, VectorIndexD>;
6912 class SIMDInsFromMain<string size, ValueType vectype,
6913                       RegisterClass regtype, Operand idxtype>
6914   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6915                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6916                    "{\t$Rd" # size # "$idx, $Rn" #
6917                    "|" # size # "\t$Rd$idx, $Rn}",
6918                    "$Rd = $dst",
6919             [(set V128:$dst,
6920               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6921   let Inst{14-11} = 0b0011;
6924 class SIMDInsFromElement<string size, ValueType vectype,
6925                          ValueType elttype, Operand idxtype>
6926   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6927                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6928                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6929                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6930                    "$Rd = $dst",
6931          [(set V128:$dst,
6932                (vector_insert
6933                  (vectype V128:$Rd),
6934                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6935                  idxtype:$idx))]>;
6937 class SIMDInsMainMovAlias<string size, Instruction inst,
6938                           RegisterClass regtype, Operand idxtype>
6939     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6940                         "|" # size #"\t$dst$idx, $src}",
6941                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6942 class SIMDInsElementMovAlias<string size, Instruction inst,
6943                              Operand idxtype>
6944     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6945                       # "|" # size #"\t$dst$idx, $src$idx2}",
6946                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6949 multiclass SIMDIns {
6950   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6951     bits<4> idx;
6952     let Inst{20-17} = idx;
6953     let Inst{16} = 1;
6954   }
6955   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6956     bits<3> idx;
6957     let Inst{20-18} = idx;
6958     let Inst{17-16} = 0b10;
6959   }
6960   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6961     bits<2> idx;
6962     let Inst{20-19} = idx;
6963     let Inst{18-16} = 0b100;
6964   }
6965   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6966     bits<1> idx;
6967     let Inst{20} = idx;
6968     let Inst{19-16} = 0b1000;
6969   }
6971   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6972     bits<4> idx;
6973     bits<4> idx2;
6974     let Inst{20-17} = idx;
6975     let Inst{16} = 1;
6976     let Inst{14-11} = idx2;
6977   }
6978   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6979     bits<3> idx;
6980     bits<3> idx2;
6981     let Inst{20-18} = idx;
6982     let Inst{17-16} = 0b10;
6983     let Inst{14-12} = idx2;
6984     let Inst{11} = {?};
6985   }
6986   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6987     bits<2> idx;
6988     bits<2> idx2;
6989     let Inst{20-19} = idx;
6990     let Inst{18-16} = 0b100;
6991     let Inst{14-13} = idx2;
6992     let Inst{12-11} = {?,?};
6993   }
6994   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6995     bits<1> idx;
6996     bits<1> idx2;
6997     let Inst{20} = idx;
6998     let Inst{19-16} = 0b1000;
6999     let Inst{14} = idx2;
7000     let Inst{13-11} = {?,?,?};
7001   }
7003   // For all forms of the INS instruction, the "mov" mnemonic is the
7004   // preferred alias. Why they didn't just call the instruction "mov" in
7005   // the first place is a very good question indeed...
7006   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7007                          GPR32, VectorIndexB>;
7008   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7009                          GPR32, VectorIndexH>;
7010   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7011                          GPR32, VectorIndexS>;
7012   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7013                          GPR64, VectorIndexD>;
7015   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7016                          VectorIndexB>;
7017   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7018                          VectorIndexH>;
7019   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7020                          VectorIndexS>;
7021   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7022                          VectorIndexD>;
7025 //----------------------------------------------------------------------------
7026 // AdvSIMD TBL/TBX
7027 //----------------------------------------------------------------------------
7029 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7030 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7031                           RegisterOperand listtype, string asm, string kind>
7032   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7033        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7034     Sched<[WriteV]> {
7035   bits<5> Vd;
7036   bits<5> Vn;
7037   bits<5> Vm;
7038   let Inst{31}    = 0;
7039   let Inst{30}    = Q;
7040   let Inst{29-21} = 0b001110000;
7041   let Inst{20-16} = Vm;
7042   let Inst{15}    = 0;
7043   let Inst{14-13} = len;
7044   let Inst{12}    = op;
7045   let Inst{11-10} = 0b00;
7046   let Inst{9-5}   = Vn;
7047   let Inst{4-0}   = Vd;
7050 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7051 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7052                           RegisterOperand listtype, string asm, string kind>
7053   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7054        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7055     Sched<[WriteV]> {
7056   bits<5> Vd;
7057   bits<5> Vn;
7058   bits<5> Vm;
7059   let Inst{31}    = 0;
7060   let Inst{30}    = Q;
7061   let Inst{29-21} = 0b001110000;
7062   let Inst{20-16} = Vm;
7063   let Inst{15}    = 0;
7064   let Inst{14-13} = len;
7065   let Inst{12}    = op;
7066   let Inst{11-10} = 0b00;
7067   let Inst{9-5}   = Vn;
7068   let Inst{4-0}   = Vd;
7071 class SIMDTableLookupAlias<string asm, Instruction inst,
7072                           RegisterOperand vectype, RegisterOperand listtype>
7073     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7074                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7076 multiclass SIMDTableLookup<bit op, string asm> {
7077   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7078                                       asm, ".8b">;
7079   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7080                                       asm, ".8b">;
7081   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7082                                       asm, ".8b">;
7083   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7084                                       asm, ".8b">;
7085   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7086                                       asm, ".16b">;
7087   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7088                                       asm, ".16b">;
7089   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7090                                       asm, ".16b">;
7091   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7092                                       asm, ".16b">;
7094   def : SIMDTableLookupAlias<asm # ".8b",
7095                          !cast<Instruction>(NAME#"v8i8One"),
7096                          V64, VecListOne128>;
7097   def : SIMDTableLookupAlias<asm # ".8b",
7098                          !cast<Instruction>(NAME#"v8i8Two"),
7099                          V64, VecListTwo128>;
7100   def : SIMDTableLookupAlias<asm # ".8b",
7101                          !cast<Instruction>(NAME#"v8i8Three"),
7102                          V64, VecListThree128>;
7103   def : SIMDTableLookupAlias<asm # ".8b",
7104                          !cast<Instruction>(NAME#"v8i8Four"),
7105                          V64, VecListFour128>;
7106   def : SIMDTableLookupAlias<asm # ".16b",
7107                          !cast<Instruction>(NAME#"v16i8One"),
7108                          V128, VecListOne128>;
7109   def : SIMDTableLookupAlias<asm # ".16b",
7110                          !cast<Instruction>(NAME#"v16i8Two"),
7111                          V128, VecListTwo128>;
7112   def : SIMDTableLookupAlias<asm # ".16b",
7113                          !cast<Instruction>(NAME#"v16i8Three"),
7114                          V128, VecListThree128>;
7115   def : SIMDTableLookupAlias<asm # ".16b",
7116                          !cast<Instruction>(NAME#"v16i8Four"),
7117                          V128, VecListFour128>;
7120 multiclass SIMDTableLookupTied<bit op, string asm> {
7121   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7122                                       asm, ".8b">;
7123   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7124                                       asm, ".8b">;
7125   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7126                                       asm, ".8b">;
7127   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7128                                       asm, ".8b">;
7129   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7130                                       asm, ".16b">;
7131   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7132                                       asm, ".16b">;
7133   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7134                                       asm, ".16b">;
7135   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7136                                       asm, ".16b">;
7138   def : SIMDTableLookupAlias<asm # ".8b",
7139                          !cast<Instruction>(NAME#"v8i8One"),
7140                          V64, VecListOne128>;
7141   def : SIMDTableLookupAlias<asm # ".8b",
7142                          !cast<Instruction>(NAME#"v8i8Two"),
7143                          V64, VecListTwo128>;
7144   def : SIMDTableLookupAlias<asm # ".8b",
7145                          !cast<Instruction>(NAME#"v8i8Three"),
7146                          V64, VecListThree128>;
7147   def : SIMDTableLookupAlias<asm # ".8b",
7148                          !cast<Instruction>(NAME#"v8i8Four"),
7149                          V64, VecListFour128>;
7150   def : SIMDTableLookupAlias<asm # ".16b",
7151                          !cast<Instruction>(NAME#"v16i8One"),
7152                          V128, VecListOne128>;
7153   def : SIMDTableLookupAlias<asm # ".16b",
7154                          !cast<Instruction>(NAME#"v16i8Two"),
7155                          V128, VecListTwo128>;
7156   def : SIMDTableLookupAlias<asm # ".16b",
7157                          !cast<Instruction>(NAME#"v16i8Three"),
7158                          V128, VecListThree128>;
7159   def : SIMDTableLookupAlias<asm # ".16b",
7160                          !cast<Instruction>(NAME#"v16i8Four"),
7161                          V128, VecListFour128>;
7165 //----------------------------------------------------------------------------
7166 // AdvSIMD scalar CPY
7167 //----------------------------------------------------------------------------
7168 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7169 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7170                         string kind, Operand idxtype>
7171   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7172        "{\t$dst, $src" # kind # "$idx" #
7173        "|\t$dst, $src$idx}", "", []>,
7174     Sched<[WriteV]> {
7175   bits<5> dst;
7176   bits<5> src;
7177   let Inst{31-21} = 0b01011110000;
7178   let Inst{15-10} = 0b000001;
7179   let Inst{9-5}   = src;
7180   let Inst{4-0}   = dst;
7183 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7184       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7185     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
7186                     # "|\t$dst, $src$index}",
7187                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7190 multiclass SIMDScalarCPY<string asm> {
7191   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7192     bits<4> idx;
7193     let Inst{20-17} = idx;
7194     let Inst{16} = 1;
7195   }
7196   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7197     bits<3> idx;
7198     let Inst{20-18} = idx;
7199     let Inst{17-16} = 0b10;
7200   }
7201   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7202     bits<2> idx;
7203     let Inst{20-19} = idx;
7204     let Inst{18-16} = 0b100;
7205   }
7206   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7207     bits<1> idx;
7208     let Inst{20} = idx;
7209     let Inst{19-16} = 0b1000;
7210   }
7212   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7213                                                           VectorIndexD:$idx)))),
7214             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7216   // 'DUP' mnemonic aliases.
7217   def : SIMDScalarCPYAlias<"dup", ".b",
7218                            !cast<Instruction>(NAME#"i8"),
7219                            FPR8, V128, VectorIndexB>;
7220   def : SIMDScalarCPYAlias<"dup", ".h",
7221                            !cast<Instruction>(NAME#"i16"),
7222                            FPR16, V128, VectorIndexH>;
7223   def : SIMDScalarCPYAlias<"dup", ".s",
7224                            !cast<Instruction>(NAME#"i32"),
7225                            FPR32, V128, VectorIndexS>;
7226   def : SIMDScalarCPYAlias<"dup", ".d",
7227                            !cast<Instruction>(NAME#"i64"),
7228                            FPR64, V128, VectorIndexD>;
7231 //----------------------------------------------------------------------------
7232 // AdvSIMD modified immediate instructions
7233 //----------------------------------------------------------------------------
7235 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7236                           string asm, string op_string,
7237                           string cstr, list<dag> pattern>
7238   : I<oops, iops, asm, op_string, cstr, pattern>,
7239     Sched<[WriteV]> {
7240   bits<5> Rd;
7241   bits<8> imm8;
7242   let Inst{31}    = 0;
7243   let Inst{30}    = Q;
7244   let Inst{29}    = op;
7245   let Inst{28-19} = 0b0111100000;
7246   let Inst{18-16} = imm8{7-5};
7247   let Inst{11} = op2;
7248   let Inst{10} = 1;
7249   let Inst{9-5}   = imm8{4-0};
7250   let Inst{4-0}   = Rd;
7253 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7254                                 Operand immtype, dag opt_shift_iop,
7255                                 string opt_shift, string asm, string kind,
7256                                 list<dag> pattern>
7257   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7258                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7259                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7260                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7261                         "", pattern> {
7262   let DecoderMethod = "DecodeModImmInstruction";
7265 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7266                                 Operand immtype, dag opt_shift_iop,
7267                                 string opt_shift, string asm, string kind,
7268                                 list<dag> pattern>
7269   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7270                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7271                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7272                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7273                         "$Rd = $dst", pattern> {
7274   let DecoderMethod = "DecodeModImmTiedInstruction";
7277 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7278                                      RegisterOperand vectype, string asm,
7279                                      string kind, list<dag> pattern>
7280   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7281                               (ins logical_vec_shift:$shift),
7282                               "$shift", asm, kind, pattern> {
7283   bits<2> shift;
7284   let Inst{15}    = b15_b12{1};
7285   let Inst{14-13} = shift;
7286   let Inst{12}    = b15_b12{0};
7289 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7290                                      RegisterOperand vectype, string asm,
7291                                      string kind, list<dag> pattern>
7292   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7293                               (ins logical_vec_shift:$shift),
7294                               "$shift", asm, kind, pattern> {
7295   bits<2> shift;
7296   let Inst{15}    = b15_b12{1};
7297   let Inst{14-13} = shift;
7298   let Inst{12}    = b15_b12{0};
7302 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7303                                          RegisterOperand vectype, string asm,
7304                                          string kind, list<dag> pattern>
7305   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7306                               (ins logical_vec_hw_shift:$shift),
7307                               "$shift", asm, kind, pattern> {
7308   bits<2> shift;
7309   let Inst{15} = b15_b12{1};
7310   let Inst{14} = 0;
7311   let Inst{13} = shift{0};
7312   let Inst{12} = b15_b12{0};
7315 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7316                                          RegisterOperand vectype, string asm,
7317                                          string kind, list<dag> pattern>
7318   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7319                               (ins logical_vec_hw_shift:$shift),
7320                               "$shift", asm, kind, pattern> {
7321   bits<2> shift;
7322   let Inst{15} = b15_b12{1};
7323   let Inst{14} = 0;
7324   let Inst{13} = shift{0};
7325   let Inst{12} = b15_b12{0};
7328 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7329                                       string asm> {
7330   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7331                                                  asm, ".4h", []>;
7332   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7333                                                  asm, ".8h", []>;
7335   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7336                                              asm, ".2s", []>;
7337   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7338                                              asm, ".4s", []>;
7341 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7342                                       bits<2> w_cmode, string asm,
7343                                       SDNode OpNode> {
7344   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7345                                                  asm, ".4h",
7346              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7347                                              imm0_255:$imm8,
7348                                              (i32 imm:$shift)))]>;
7349   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7350                                                  asm, ".8h",
7351              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7352                                               imm0_255:$imm8,
7353                                               (i32 imm:$shift)))]>;
7355   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7356                                              asm, ".2s",
7357              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7358                                              imm0_255:$imm8,
7359                                              (i32 imm:$shift)))]>;
7360   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7361                                              asm, ".4s",
7362              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7363                                               imm0_255:$imm8,
7364                                               (i32 imm:$shift)))]>;
7367 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7368                              RegisterOperand vectype, string asm,
7369                              string kind, list<dag> pattern>
7370   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7371                               (ins move_vec_shift:$shift),
7372                               "$shift", asm, kind, pattern> {
7373   bits<1> shift;
7374   let Inst{15-13} = cmode{3-1};
7375   let Inst{12}    = shift;
7378 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7379                                    RegisterOperand vectype,
7380                                    Operand imm_type, string asm,
7381                                    string kind, list<dag> pattern>
7382   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7383                               asm, kind, pattern> {
7384   let Inst{15-12} = cmode;
7387 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7388                                    list<dag> pattern>
7389   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7390                         "\t$Rd, $imm8", "", pattern> {
7391   let Inst{15-12} = cmode;
7392   let DecoderMethod = "DecodeModImmInstruction";
7395 //----------------------------------------------------------------------------
7396 // AdvSIMD indexed element
7397 //----------------------------------------------------------------------------
7399 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7400 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7401                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7402                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7403                       string apple_kind, string dst_kind, string lhs_kind,
7404                       string rhs_kind, list<dag> pattern>
7405   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7406       asm,
7407       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7408       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7409     Sched<[WriteV]> {
7410   bits<5> Rd;
7411   bits<5> Rn;
7412   bits<5> Rm;
7414   let Inst{31}    = 0;
7415   let Inst{30}    = Q;
7416   let Inst{29}    = U;
7417   let Inst{28}    = Scalar;
7418   let Inst{27-24} = 0b1111;
7419   let Inst{23-22} = size;
7420   // Bit 21 must be set by the derived class.
7421   let Inst{20-16} = Rm;
7422   let Inst{15-12} = opc;
7423   // Bit 11 must be set by the derived class.
7424   let Inst{10}    = 0;
7425   let Inst{9-5}   = Rn;
7426   let Inst{4-0}   = Rd;
7429 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7430 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7431                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7432                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7433                       string apple_kind, string dst_kind, string lhs_kind,
7434                       string rhs_kind, list<dag> pattern>
7435   : I<(outs dst_reg:$dst),
7436       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7437       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7438       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7439     Sched<[WriteV]> {
7440   bits<5> Rd;
7441   bits<5> Rn;
7442   bits<5> Rm;
7444   let Inst{31}    = 0;
7445   let Inst{30}    = Q;
7446   let Inst{29}    = U;
7447   let Inst{28}    = Scalar;
7448   let Inst{27-24} = 0b1111;
7449   let Inst{23-22} = size;
7450   // Bit 21 must be set by the derived class.
7451   let Inst{20-16} = Rm;
7452   let Inst{15-12} = opc;
7453   // Bit 11 must be set by the derived class.
7454   let Inst{10}    = 0;
7455   let Inst{9-5}   = Rn;
7456   let Inst{4-0}   = Rd;
7459 // ARMv8.2-A Dot Product Instructions (Indexed)
7460 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7461                                       string lhs_kind, string rhs_kind,
7462                                       RegisterOperand RegType,
7463                                       ValueType AccumType, ValueType InputType,
7464                                       SDPatternOperator OpNode> :
7465         BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7466                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7467         [(set (AccumType RegType:$dst),
7468               (AccumType (OpNode (AccumType RegType:$Rd),
7469                                  (InputType RegType:$Rn),
7470                                  (InputType (bitconvert (AccumType
7471                                     (AArch64duplane32 (v4i32 V128:$Rm),
7472                                         VectorIndexS:$idx)))))))]> {
7473   bits<2> idx;
7474   let Inst{21}    = idx{0};  // L
7475   let Inst{11}    = idx{1};  // H
7478 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7479                                        SDPatternOperator OpNode> {
7480   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b",
7481                                               V64, v2i32, v8i8, OpNode>;
7482   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b",
7483                                               V128, v4i32, v16i8, OpNode>;
7486 // ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7487 class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7488                                       string dst_kind, string lhs_kind,
7489                                       string rhs_kind, RegisterOperand RegType,
7490                                       ValueType AccumType, ValueType InputType,
7491                                       SDPatternOperator OpNode> :
7492         BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7493                             VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7494           [(set (AccumType RegType:$dst),
7495                 (AccumType (OpNode (AccumType RegType:$Rd),
7496                                    (InputType RegType:$Rn),
7497                                    (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7498                                                 VectorIndexH:$idx)))))]> {
7499   // idx = H:L:M
7500   bits<3> idx;
7501   let Inst{11} = idx{2}; // H
7502   let Inst{21} = idx{1}; // L
7503   let Inst{20} = idx{0}; // M
7506 multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
7507                                        SDPatternOperator OpNode> {
7508   def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
7509                                               V64, v2f32, v4f16, OpNode>;
7510   def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
7511                                               V128, v4f32, v8f16, OpNode>;
7514 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7515                          SDPatternOperator OpNode> {
7516   let Predicates = [HasNEON, HasFullFP16] in {
7517   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7518                                       V64, V64,
7519                                       V128_lo, VectorIndexH,
7520                                       asm, ".4h", ".4h", ".4h", ".h",
7521     [(set (v4f16 V64:$Rd),
7522         (OpNode (v4f16 V64:$Rn),
7523          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7524     bits<3> idx;
7525     let Inst{11} = idx{2};
7526     let Inst{21} = idx{1};
7527     let Inst{20} = idx{0};
7528   }
7530   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7531                                       V128, V128,
7532                                       V128_lo, VectorIndexH,
7533                                       asm, ".8h", ".8h", ".8h", ".h",
7534     [(set (v8f16 V128:$Rd),
7535         (OpNode (v8f16 V128:$Rn),
7536          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7537     bits<3> idx;
7538     let Inst{11} = idx{2};
7539     let Inst{21} = idx{1};
7540     let Inst{20} = idx{0};
7541   }
7542   } // Predicates = [HasNEON, HasFullFP16]
7544   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7545                                       V64, V64,
7546                                       V128, VectorIndexS,
7547                                       asm, ".2s", ".2s", ".2s", ".s",
7548     [(set (v2f32 V64:$Rd),
7549         (OpNode (v2f32 V64:$Rn),
7550          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7551     bits<2> idx;
7552     let Inst{11} = idx{1};
7553     let Inst{21} = idx{0};
7554   }
7556   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7557                                       V128, V128,
7558                                       V128, VectorIndexS,
7559                                       asm, ".4s", ".4s", ".4s", ".s",
7560     [(set (v4f32 V128:$Rd),
7561         (OpNode (v4f32 V128:$Rn),
7562          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7563     bits<2> idx;
7564     let Inst{11} = idx{1};
7565     let Inst{21} = idx{0};
7566   }
7568   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7569                                       V128, V128,
7570                                       V128, VectorIndexD,
7571                                       asm, ".2d", ".2d", ".2d", ".d",
7572     [(set (v2f64 V128:$Rd),
7573         (OpNode (v2f64 V128:$Rn),
7574          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7575     bits<1> idx;
7576     let Inst{11} = idx{0};
7577     let Inst{21} = 0;
7578   }
7580   let Predicates = [HasNEON, HasFullFP16] in {
7581   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7582                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7583                                       asm, ".h", "", "", ".h",
7584     [(set (f16 FPR16Op:$Rd),
7585           (OpNode (f16 FPR16Op:$Rn),
7586                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
7587                                        VectorIndexH:$idx))))]> {
7588     bits<3> idx;
7589     let Inst{11} = idx{2};
7590     let Inst{21} = idx{1};
7591     let Inst{20} = idx{0};
7592   }
7593   } // Predicates = [HasNEON, HasFullFP16]
7595   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7596                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7597                                       asm, ".s", "", "", ".s",
7598     [(set (f32 FPR32Op:$Rd),
7599           (OpNode (f32 FPR32Op:$Rn),
7600                   (f32 (vector_extract (v4f32 V128:$Rm),
7601                                        VectorIndexS:$idx))))]> {
7602     bits<2> idx;
7603     let Inst{11} = idx{1};
7604     let Inst{21} = idx{0};
7605   }
7607   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7608                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7609                                       asm, ".d", "", "", ".d",
7610     [(set (f64 FPR64Op:$Rd),
7611           (OpNode (f64 FPR64Op:$Rn),
7612                   (f64 (vector_extract (v2f64 V128:$Rm),
7613                                        VectorIndexD:$idx))))]> {
7614     bits<1> idx;
7615     let Inst{11} = idx{0};
7616     let Inst{21} = 0;
7617   }
7620 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7621   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7622   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7623                            (AArch64duplane32 (v4f32 V128:$Rm),
7624                                            VectorIndexS:$idx))),
7625             (!cast<Instruction>(INST # v2i32_indexed)
7626                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7627   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7628                            (AArch64dup (f32 FPR32Op:$Rm)))),
7629             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7630                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7633   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7634   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7635                            (AArch64duplane32 (v4f32 V128:$Rm),
7636                                            VectorIndexS:$idx))),
7637             (!cast<Instruction>(INST # "v4i32_indexed")
7638                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7639   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7640                            (AArch64dup (f32 FPR32Op:$Rm)))),
7641             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7642                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7644   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7645   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7646                            (AArch64duplane64 (v2f64 V128:$Rm),
7647                                            VectorIndexD:$idx))),
7648             (!cast<Instruction>(INST # "v2i64_indexed")
7649                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7650   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7651                            (AArch64dup (f64 FPR64Op:$Rm)))),
7652             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7653                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7655   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7656   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7657                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7658             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7659                 V128:$Rm, VectorIndexS:$idx)>;
7660   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7661                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7662             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7663                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7665   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7666   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7667                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7668             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7669                 V128:$Rm, VectorIndexD:$idx)>;
7672 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7673   let Predicates = [HasNEON, HasFullFP16] in {
7674   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7675                                           V128_lo, VectorIndexH,
7676                                           asm, ".4h", ".4h", ".4h", ".h", []> {
7677     bits<3> idx;
7678     let Inst{11} = idx{2};
7679     let Inst{21} = idx{1};
7680     let Inst{20} = idx{0};
7681   }
7683   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7684                                           V128, V128,
7685                                           V128_lo, VectorIndexH,
7686                                           asm, ".8h", ".8h", ".8h", ".h", []> {
7687     bits<3> idx;
7688     let Inst{11} = idx{2};
7689     let Inst{21} = idx{1};
7690     let Inst{20} = idx{0};
7691   }
7692   } // Predicates = [HasNEON, HasFullFP16]
7694   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7695                                           V128, VectorIndexS,
7696                                           asm, ".2s", ".2s", ".2s", ".s", []> {
7697     bits<2> idx;
7698     let Inst{11} = idx{1};
7699     let Inst{21} = idx{0};
7700   }
7702   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7703                                       V128, V128,
7704                                       V128, VectorIndexS,
7705                                       asm, ".4s", ".4s", ".4s", ".s", []> {
7706     bits<2> idx;
7707     let Inst{11} = idx{1};
7708     let Inst{21} = idx{0};
7709   }
7711   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7712                                       V128, V128,
7713                                       V128, VectorIndexD,
7714                                       asm, ".2d", ".2d", ".2d", ".d", []> {
7715     bits<1> idx;
7716     let Inst{11} = idx{0};
7717     let Inst{21} = 0;
7718   }
7720   let Predicates = [HasNEON, HasFullFP16] in {
7721   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7722                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7723                                       asm, ".h", "", "", ".h", []> {
7724     bits<3> idx;
7725     let Inst{11} = idx{2};
7726     let Inst{21} = idx{1};
7727     let Inst{20} = idx{0};
7728   }
7729   } // Predicates = [HasNEON, HasFullFP16]
7731   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7732                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7733                                       asm, ".s", "", "", ".s", []> {
7734     bits<2> idx;
7735     let Inst{11} = idx{1};
7736     let Inst{21} = idx{0};
7737   }
7739   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7740                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7741                                       asm, ".d", "", "", ".d", []> {
7742     bits<1> idx;
7743     let Inst{11} = idx{0};
7744     let Inst{21} = 0;
7745   }
7748 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7749                          SDPatternOperator OpNode> {
7750   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7751                                       V128_lo, VectorIndexH,
7752                                       asm, ".4h", ".4h", ".4h", ".h",
7753     [(set (v4i16 V64:$Rd),
7754         (OpNode (v4i16 V64:$Rn),
7755          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7756     bits<3> idx;
7757     let Inst{11} = idx{2};
7758     let Inst{21} = idx{1};
7759     let Inst{20} = idx{0};
7760   }
7762   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7763                                       V128, V128,
7764                                       V128_lo, VectorIndexH,
7765                                       asm, ".8h", ".8h", ".8h", ".h",
7766     [(set (v8i16 V128:$Rd),
7767        (OpNode (v8i16 V128:$Rn),
7768          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7769     bits<3> idx;
7770     let Inst{11} = idx{2};
7771     let Inst{21} = idx{1};
7772     let Inst{20} = idx{0};
7773   }
7775   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7776                                       V64, V64,
7777                                       V128, VectorIndexS,
7778                                       asm, ".2s", ".2s", ".2s",  ".s",
7779     [(set (v2i32 V64:$Rd),
7780        (OpNode (v2i32 V64:$Rn),
7781           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7782     bits<2> idx;
7783     let Inst{11} = idx{1};
7784     let Inst{21} = idx{0};
7785   }
7787   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7788                                       V128, V128,
7789                                       V128, VectorIndexS,
7790                                       asm, ".4s", ".4s", ".4s", ".s",
7791     [(set (v4i32 V128:$Rd),
7792        (OpNode (v4i32 V128:$Rn),
7793           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7794     bits<2> idx;
7795     let Inst{11} = idx{1};
7796     let Inst{21} = idx{0};
7797   }
7799   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7800                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7801                                       asm, ".h", "", "", ".h", []> {
7802     bits<3> idx;
7803     let Inst{11} = idx{2};
7804     let Inst{21} = idx{1};
7805     let Inst{20} = idx{0};
7806   }
7808   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7809                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7810                                       asm, ".s", "", "", ".s",
7811       [(set (i32 FPR32Op:$Rd),
7812             (OpNode FPR32Op:$Rn,
7813                     (i32 (vector_extract (v4i32 V128:$Rm),
7814                                          VectorIndexS:$idx))))]> {
7815     bits<2> idx;
7816     let Inst{11} = idx{1};
7817     let Inst{21} = idx{0};
7818   }
7821 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7822                                SDPatternOperator OpNode> {
7823   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7824                                       V64, V64,
7825                                       V128_lo, VectorIndexH,
7826                                       asm, ".4h", ".4h", ".4h", ".h",
7827     [(set (v4i16 V64:$Rd),
7828         (OpNode (v4i16 V64:$Rn),
7829          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7830     bits<3> idx;
7831     let Inst{11} = idx{2};
7832     let Inst{21} = idx{1};
7833     let Inst{20} = idx{0};
7834   }
7836   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7837                                       V128, V128,
7838                                       V128_lo, VectorIndexH,
7839                                       asm, ".8h", ".8h", ".8h", ".h",
7840     [(set (v8i16 V128:$Rd),
7841        (OpNode (v8i16 V128:$Rn),
7842          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7843     bits<3> idx;
7844     let Inst{11} = idx{2};
7845     let Inst{21} = idx{1};
7846     let Inst{20} = idx{0};
7847   }
7849   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7850                                       V64, V64,
7851                                       V128, VectorIndexS,
7852                                       asm, ".2s", ".2s", ".2s", ".s",
7853     [(set (v2i32 V64:$Rd),
7854        (OpNode (v2i32 V64:$Rn),
7855           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7856     bits<2> idx;
7857     let Inst{11} = idx{1};
7858     let Inst{21} = idx{0};
7859   }
7861   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7862                                       V128, V128,
7863                                       V128, VectorIndexS,
7864                                       asm, ".4s", ".4s", ".4s", ".s",
7865     [(set (v4i32 V128:$Rd),
7866        (OpNode (v4i32 V128:$Rn),
7867           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7868     bits<2> idx;
7869     let Inst{11} = idx{1};
7870     let Inst{21} = idx{0};
7871   }
7874 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7875                                    SDPatternOperator OpNode> {
7876   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7877                                           V128_lo, VectorIndexH,
7878                                           asm, ".4h", ".4h", ".4h", ".h",
7879     [(set (v4i16 V64:$dst),
7880         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7881          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7882     bits<3> idx;
7883     let Inst{11} = idx{2};
7884     let Inst{21} = idx{1};
7885     let Inst{20} = idx{0};
7886   }
7888   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7889                                       V128, V128,
7890                                       V128_lo, VectorIndexH,
7891                                       asm, ".8h", ".8h", ".8h", ".h",
7892     [(set (v8i16 V128:$dst),
7893        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7894          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7895     bits<3> idx;
7896     let Inst{11} = idx{2};
7897     let Inst{21} = idx{1};
7898     let Inst{20} = idx{0};
7899   }
7901   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7902                                       V64, V64,
7903                                       V128, VectorIndexS,
7904                                       asm, ".2s", ".2s", ".2s", ".s",
7905     [(set (v2i32 V64:$dst),
7906        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7907           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7908     bits<2> idx;
7909     let Inst{11} = idx{1};
7910     let Inst{21} = idx{0};
7911   }
7913   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7914                                       V128, V128,
7915                                       V128, VectorIndexS,
7916                                       asm, ".4s", ".4s", ".4s", ".s",
7917     [(set (v4i32 V128:$dst),
7918        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7919           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7920     bits<2> idx;
7921     let Inst{11} = idx{1};
7922     let Inst{21} = idx{0};
7923   }
7926 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7927                              SDPatternOperator OpNode> {
7928   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7929                                       V128, V64,
7930                                       V128_lo, VectorIndexH,
7931                                       asm, ".4s", ".4s", ".4h", ".h",
7932     [(set (v4i32 V128:$Rd),
7933         (OpNode (v4i16 V64:$Rn),
7934          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7935     bits<3> idx;
7936     let Inst{11} = idx{2};
7937     let Inst{21} = idx{1};
7938     let Inst{20} = idx{0};
7939   }
7941   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7942                                       V128, V128,
7943                                       V128_lo, VectorIndexH,
7944                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7945     [(set (v4i32 V128:$Rd),
7946           (OpNode (extract_high_v8i16 V128:$Rn),
7947                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7948                                                       VectorIndexH:$idx))))]> {
7950     bits<3> idx;
7951     let Inst{11} = idx{2};
7952     let Inst{21} = idx{1};
7953     let Inst{20} = idx{0};
7954   }
7956   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7957                                       V128, V64,
7958                                       V128, VectorIndexS,
7959                                       asm, ".2d", ".2d", ".2s", ".s",
7960     [(set (v2i64 V128:$Rd),
7961         (OpNode (v2i32 V64:$Rn),
7962          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7963     bits<2> idx;
7964     let Inst{11} = idx{1};
7965     let Inst{21} = idx{0};
7966   }
7968   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7969                                       V128, V128,
7970                                       V128, VectorIndexS,
7971                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7972     [(set (v2i64 V128:$Rd),
7973           (OpNode (extract_high_v4i32 V128:$Rn),
7974                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7975                                                       VectorIndexS:$idx))))]> {
7976     bits<2> idx;
7977     let Inst{11} = idx{1};
7978     let Inst{21} = idx{0};
7979   }
7981   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7982                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7983                                       asm, ".h", "", "", ".h", []> {
7984     bits<3> idx;
7985     let Inst{11} = idx{2};
7986     let Inst{21} = idx{1};
7987     let Inst{20} = idx{0};
7988   }
7990   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7991                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7992                                       asm, ".s", "", "", ".s", []> {
7993     bits<2> idx;
7994     let Inst{11} = idx{1};
7995     let Inst{21} = idx{0};
7996   }
7999 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8000                                        SDPatternOperator Accum> {
8001   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8002                                       V128, V64,
8003                                       V128_lo, VectorIndexH,
8004                                       asm, ".4s", ".4s", ".4h", ".h",
8005     [(set (v4i32 V128:$dst),
8006           (Accum (v4i32 V128:$Rd),
8007                  (v4i32 (int_aarch64_neon_sqdmull
8008                              (v4i16 V64:$Rn),
8009                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8010                                                     VectorIndexH:$idx))))))]> {
8011     bits<3> idx;
8012     let Inst{11} = idx{2};
8013     let Inst{21} = idx{1};
8014     let Inst{20} = idx{0};
8015   }
8017   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8018   // intermediate EXTRACT_SUBREG would be untyped.
8019   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8020                 (i32 (vector_extract (v4i32
8021                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8022                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8023                                                     VectorIndexH:$idx)))),
8024                          (i64 0))))),
8025             (EXTRACT_SUBREG
8026                 (!cast<Instruction>(NAME # v4i16_indexed)
8027                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8028                     V128_lo:$Rm, VectorIndexH:$idx),
8029                 ssub)>;
8031   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8032                                       V128, V128,
8033                                       V128_lo, VectorIndexH,
8034                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8035     [(set (v4i32 V128:$dst),
8036           (Accum (v4i32 V128:$Rd),
8037                  (v4i32 (int_aarch64_neon_sqdmull
8038                             (extract_high_v8i16 V128:$Rn),
8039                             (extract_high_v8i16
8040                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8041                                                 VectorIndexH:$idx))))))]> {
8042     bits<3> idx;
8043     let Inst{11} = idx{2};
8044     let Inst{21} = idx{1};
8045     let Inst{20} = idx{0};
8046   }
8048   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8049                                       V128, V64,
8050                                       V128, VectorIndexS,
8051                                       asm, ".2d", ".2d", ".2s", ".s",
8052     [(set (v2i64 V128:$dst),
8053         (Accum (v2i64 V128:$Rd),
8054                (v2i64 (int_aarch64_neon_sqdmull
8055                           (v2i32 V64:$Rn),
8056                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8057                                                  VectorIndexS:$idx))))))]> {
8058     bits<2> idx;
8059     let Inst{11} = idx{1};
8060     let Inst{21} = idx{0};
8061   }
8063   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8064                                       V128, V128,
8065                                       V128, VectorIndexS,
8066                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8067     [(set (v2i64 V128:$dst),
8068           (Accum (v2i64 V128:$Rd),
8069                  (v2i64 (int_aarch64_neon_sqdmull
8070                             (extract_high_v4i32 V128:$Rn),
8071                             (extract_high_v4i32
8072                                 (AArch64duplane32 (v4i32 V128:$Rm),
8073                                                 VectorIndexS:$idx))))))]> {
8074     bits<2> idx;
8075     let Inst{11} = idx{1};
8076     let Inst{21} = idx{0};
8077   }
8079   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8080                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8081                                       asm, ".h", "", "", ".h", []> {
8082     bits<3> idx;
8083     let Inst{11} = idx{2};
8084     let Inst{21} = idx{1};
8085     let Inst{20} = idx{0};
8086   }
8089   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8090                                       FPR64Op, FPR32Op, V128, VectorIndexS,
8091                                       asm, ".s", "", "", ".s",
8092     [(set (i64 FPR64Op:$dst),
8093           (Accum (i64 FPR64Op:$Rd),
8094                  (i64 (int_aarch64_neon_sqdmulls_scalar
8095                             (i32 FPR32Op:$Rn),
8096                             (i32 (vector_extract (v4i32 V128:$Rm),
8097                                                  VectorIndexS:$idx))))))]> {
8099     bits<2> idx;
8100     let Inst{11} = idx{1};
8101     let Inst{21} = idx{0};
8102   }
8105 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8106                                    SDPatternOperator OpNode> {
8107   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8108   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8109                                       V128, V64,
8110                                       V128_lo, VectorIndexH,
8111                                       asm, ".4s", ".4s", ".4h", ".h",
8112     [(set (v4i32 V128:$Rd),
8113         (OpNode (v4i16 V64:$Rn),
8114          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8115     bits<3> idx;
8116     let Inst{11} = idx{2};
8117     let Inst{21} = idx{1};
8118     let Inst{20} = idx{0};
8119   }
8121   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8122                                       V128, V128,
8123                                       V128_lo, VectorIndexH,
8124                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8125     [(set (v4i32 V128:$Rd),
8126           (OpNode (extract_high_v8i16 V128:$Rn),
8127                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8128                                                       VectorIndexH:$idx))))]> {
8130     bits<3> idx;
8131     let Inst{11} = idx{2};
8132     let Inst{21} = idx{1};
8133     let Inst{20} = idx{0};
8134   }
8136   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8137                                       V128, V64,
8138                                       V128, VectorIndexS,
8139                                       asm, ".2d", ".2d", ".2s", ".s",
8140     [(set (v2i64 V128:$Rd),
8141         (OpNode (v2i32 V64:$Rn),
8142          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8143     bits<2> idx;
8144     let Inst{11} = idx{1};
8145     let Inst{21} = idx{0};
8146   }
8148   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8149                                       V128, V128,
8150                                       V128, VectorIndexS,
8151                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8152     [(set (v2i64 V128:$Rd),
8153           (OpNode (extract_high_v4i32 V128:$Rn),
8154                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8155                                                       VectorIndexS:$idx))))]> {
8156     bits<2> idx;
8157     let Inst{11} = idx{1};
8158     let Inst{21} = idx{0};
8159   }
8160   }
8163 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8164                                        SDPatternOperator OpNode> {
8165   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8166   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8167                                       V128, V64,
8168                                       V128_lo, VectorIndexH,
8169                                       asm, ".4s", ".4s", ".4h", ".h",
8170     [(set (v4i32 V128:$dst),
8171         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8172          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8173     bits<3> idx;
8174     let Inst{11} = idx{2};
8175     let Inst{21} = idx{1};
8176     let Inst{20} = idx{0};
8177   }
8179   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8180                                       V128, V128,
8181                                       V128_lo, VectorIndexH,
8182                                       asm#"2", ".4s", ".4s", ".8h", ".h",
8183     [(set (v4i32 V128:$dst),
8184           (OpNode (v4i32 V128:$Rd),
8185                   (extract_high_v8i16 V128:$Rn),
8186                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8187                                                       VectorIndexH:$idx))))]> {
8188     bits<3> idx;
8189     let Inst{11} = idx{2};
8190     let Inst{21} = idx{1};
8191     let Inst{20} = idx{0};
8192   }
8194   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8195                                       V128, V64,
8196                                       V128, VectorIndexS,
8197                                       asm, ".2d", ".2d", ".2s", ".s",
8198     [(set (v2i64 V128:$dst),
8199         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8200          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8201     bits<2> idx;
8202     let Inst{11} = idx{1};
8203     let Inst{21} = idx{0};
8204   }
8206   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8207                                       V128, V128,
8208                                       V128, VectorIndexS,
8209                                       asm#"2", ".2d", ".2d", ".4s", ".s",
8210     [(set (v2i64 V128:$dst),
8211           (OpNode (v2i64 V128:$Rd),
8212                   (extract_high_v4i32 V128:$Rn),
8213                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8214                                                       VectorIndexS:$idx))))]> {
8215     bits<2> idx;
8216     let Inst{11} = idx{1};
8217     let Inst{21} = idx{0};
8218   }
8219   }
8222 //----------------------------------------------------------------------------
8223 // AdvSIMD scalar shift by immediate
8224 //----------------------------------------------------------------------------
8226 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8227 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8228                      RegisterClass regtype1, RegisterClass regtype2,
8229                      Operand immtype, string asm, list<dag> pattern>
8230   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8231       asm, "\t$Rd, $Rn, $imm", "", pattern>,
8232     Sched<[WriteV]> {
8233   bits<5> Rd;
8234   bits<5> Rn;
8235   bits<7> imm;
8236   let Inst{31-30} = 0b01;
8237   let Inst{29}    = U;
8238   let Inst{28-23} = 0b111110;
8239   let Inst{22-16} = fixed_imm;
8240   let Inst{15-11} = opc;
8241   let Inst{10}    = 1;
8242   let Inst{9-5} = Rn;
8243   let Inst{4-0} = Rd;
8246 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8247 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8248                      RegisterClass regtype1, RegisterClass regtype2,
8249                      Operand immtype, string asm, list<dag> pattern>
8250   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8251       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8252     Sched<[WriteV]> {
8253   bits<5> Rd;
8254   bits<5> Rn;
8255   bits<7> imm;
8256   let Inst{31-30} = 0b01;
8257   let Inst{29}    = U;
8258   let Inst{28-23} = 0b111110;
8259   let Inst{22-16} = fixed_imm;
8260   let Inst{15-11} = opc;
8261   let Inst{10}    = 1;
8262   let Inst{9-5} = Rn;
8263   let Inst{4-0} = Rd;
8267 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8268   let Predicates = [HasNEON, HasFullFP16] in {
8269   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8270                               FPR16, FPR16, vecshiftR16, asm, []> {
8271     let Inst{19-16} = imm{3-0};
8272   }
8273   } // Predicates = [HasNEON, HasFullFP16]
8274   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8275                               FPR32, FPR32, vecshiftR32, asm, []> {
8276     let Inst{20-16} = imm{4-0};
8277   }
8278   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8279                               FPR64, FPR64, vecshiftR64, asm, []> {
8280     let Inst{21-16} = imm{5-0};
8281   }
8284 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8285                              SDPatternOperator OpNode> {
8286   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8287                               FPR64, FPR64, vecshiftR64, asm,
8288   [(set (i64 FPR64:$Rd),
8289      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8290     let Inst{21-16} = imm{5-0};
8291   }
8293   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8294             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8297 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8298                                  SDPatternOperator OpNode = null_frag> {
8299   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8300                               FPR64, FPR64, vecshiftR64, asm,
8301   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8302                                                    (i32 vecshiftR64:$imm)))]> {
8303     let Inst{21-16} = imm{5-0};
8304   }
8306   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8307                            (i32 vecshiftR64:$imm))),
8308             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8309                                             vecshiftR64:$imm)>;
8312 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8313                              SDPatternOperator OpNode> {
8314   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8315                               FPR64, FPR64, vecshiftL64, asm,
8316     [(set (v1i64 FPR64:$Rd),
8317        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8318     let Inst{21-16} = imm{5-0};
8319   }
8322 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8323 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8324   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8325                               FPR64, FPR64, vecshiftL64, asm, []> {
8326     let Inst{21-16} = imm{5-0};
8327   }
8330 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8331 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8332                                SDPatternOperator OpNode = null_frag> {
8333   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8334                               FPR8, FPR16, vecshiftR8, asm, []> {
8335     let Inst{18-16} = imm{2-0};
8336   }
8338   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8339                               FPR16, FPR32, vecshiftR16, asm, []> {
8340     let Inst{19-16} = imm{3-0};
8341   }
8343   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8344                               FPR32, FPR64, vecshiftR32, asm,
8345     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8346     let Inst{20-16} = imm{4-0};
8347   }
8350 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8351                                 SDPatternOperator OpNode> {
8352   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8353                               FPR8, FPR8, vecshiftL8, asm, []> {
8354     let Inst{18-16} = imm{2-0};
8355   }
8357   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8358                               FPR16, FPR16, vecshiftL16, asm, []> {
8359     let Inst{19-16} = imm{3-0};
8360   }
8362   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8363                               FPR32, FPR32, vecshiftL32, asm,
8364     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8365     let Inst{20-16} = imm{4-0};
8366   }
8368   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8369                               FPR64, FPR64, vecshiftL64, asm,
8370     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8371     let Inst{21-16} = imm{5-0};
8372   }
8374   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8375             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8378 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8379   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8380                               FPR8, FPR8, vecshiftR8, asm, []> {
8381     let Inst{18-16} = imm{2-0};
8382   }
8384   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8385                               FPR16, FPR16, vecshiftR16, asm, []> {
8386     let Inst{19-16} = imm{3-0};
8387   }
8389   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8390                               FPR32, FPR32, vecshiftR32, asm, []> {
8391     let Inst{20-16} = imm{4-0};
8392   }
8394   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8395                               FPR64, FPR64, vecshiftR64, asm, []> {
8396     let Inst{21-16} = imm{5-0};
8397   }
8400 //----------------------------------------------------------------------------
8401 // AdvSIMD vector x indexed element
8402 //----------------------------------------------------------------------------
8404 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8405 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8406                      RegisterOperand dst_reg, RegisterOperand src_reg,
8407                      Operand immtype,
8408                      string asm, string dst_kind, string src_kind,
8409                      list<dag> pattern>
8410   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8411       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8412            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8413     Sched<[WriteV]> {
8414   bits<5> Rd;
8415   bits<5> Rn;
8416   let Inst{31}    = 0;
8417   let Inst{30}    = Q;
8418   let Inst{29}    = U;
8419   let Inst{28-23} = 0b011110;
8420   let Inst{22-16} = fixed_imm;
8421   let Inst{15-11} = opc;
8422   let Inst{10}    = 1;
8423   let Inst{9-5}   = Rn;
8424   let Inst{4-0}   = Rd;
8427 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8428 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8429                      RegisterOperand vectype1, RegisterOperand vectype2,
8430                      Operand immtype,
8431                      string asm, string dst_kind, string src_kind,
8432                      list<dag> pattern>
8433   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8434       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8435            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8436     Sched<[WriteV]> {
8437   bits<5> Rd;
8438   bits<5> Rn;
8439   let Inst{31}    = 0;
8440   let Inst{30}    = Q;
8441   let Inst{29}    = U;
8442   let Inst{28-23} = 0b011110;
8443   let Inst{22-16} = fixed_imm;
8444   let Inst{15-11} = opc;
8445   let Inst{10}    = 1;
8446   let Inst{9-5}   = Rn;
8447   let Inst{4-0}   = Rd;
8450 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8451                               Intrinsic OpNode> {
8452   let Predicates = [HasNEON, HasFullFP16] in {
8453   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8454                                   V64, V64, vecshiftR16,
8455                                   asm, ".4h", ".4h",
8456       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8457     bits<4> imm;
8458     let Inst{19-16} = imm;
8459   }
8461   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8462                                   V128, V128, vecshiftR16,
8463                                   asm, ".8h", ".8h",
8464       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8465     bits<4> imm;
8466     let Inst{19-16} = imm;
8467   }
8468   } // Predicates = [HasNEON, HasFullFP16]
8469   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8470                                   V64, V64, vecshiftR32,
8471                                   asm, ".2s", ".2s",
8472       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8473     bits<5> imm;
8474     let Inst{20-16} = imm;
8475   }
8477   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8478                                   V128, V128, vecshiftR32,
8479                                   asm, ".4s", ".4s",
8480       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8481     bits<5> imm;
8482     let Inst{20-16} = imm;
8483   }
8485   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8486                                   V128, V128, vecshiftR64,
8487                                   asm, ".2d", ".2d",
8488       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8489     bits<6> imm;
8490     let Inst{21-16} = imm;
8491   }
8494 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8495                                   Intrinsic OpNode> {
8496   let Predicates = [HasNEON, HasFullFP16] in {
8497   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8498                                   V64, V64, vecshiftR16,
8499                                   asm, ".4h", ".4h",
8500       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8501     bits<4> imm;
8502     let Inst{19-16} = imm;
8503   }
8505   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8506                                   V128, V128, vecshiftR16,
8507                                   asm, ".8h", ".8h",
8508       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8509     bits<4> imm;
8510     let Inst{19-16} = imm;
8511   }
8512   } // Predicates = [HasNEON, HasFullFP16]
8514   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8515                                   V64, V64, vecshiftR32,
8516                                   asm, ".2s", ".2s",
8517       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8518     bits<5> imm;
8519     let Inst{20-16} = imm;
8520   }
8522   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8523                                   V128, V128, vecshiftR32,
8524                                   asm, ".4s", ".4s",
8525       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8526     bits<5> imm;
8527     let Inst{20-16} = imm;
8528   }
8530   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8531                                   V128, V128, vecshiftR64,
8532                                   asm, ".2d", ".2d",
8533       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8534     bits<6> imm;
8535     let Inst{21-16} = imm;
8536   }
8539 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8540                                      SDPatternOperator OpNode> {
8541   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8542                                   V64, V128, vecshiftR16Narrow,
8543                                   asm, ".8b", ".8h",
8544       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8545     bits<3> imm;
8546     let Inst{18-16} = imm;
8547   }
8549   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8550                                   V128, V128, vecshiftR16Narrow,
8551                                   asm#"2", ".16b", ".8h", []> {
8552     bits<3> imm;
8553     let Inst{18-16} = imm;
8554     let hasSideEffects = 0;
8555   }
8557   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8558                                   V64, V128, vecshiftR32Narrow,
8559                                   asm, ".4h", ".4s",
8560       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8561     bits<4> imm;
8562     let Inst{19-16} = imm;
8563   }
8565   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8566                                   V128, V128, vecshiftR32Narrow,
8567                                   asm#"2", ".8h", ".4s", []> {
8568     bits<4> imm;
8569     let Inst{19-16} = imm;
8570     let hasSideEffects = 0;
8571   }
8573   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8574                                   V64, V128, vecshiftR64Narrow,
8575                                   asm, ".2s", ".2d",
8576       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8577     bits<5> imm;
8578     let Inst{20-16} = imm;
8579   }
8581   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8582                                   V128, V128, vecshiftR64Narrow,
8583                                   asm#"2", ".4s", ".2d", []> {
8584     bits<5> imm;
8585     let Inst{20-16} = imm;
8586     let hasSideEffects = 0;
8587   }
8589   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8590   // themselves, so put them here instead.
8592   // Patterns involving what's effectively an insert high and a normal
8593   // intrinsic, represented by CONCAT_VECTORS.
8594   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8595                                                    vecshiftR16Narrow:$imm)),
8596             (!cast<Instruction>(NAME # "v16i8_shift")
8597                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8598                 V128:$Rn, vecshiftR16Narrow:$imm)>;
8599   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8600                                                      vecshiftR32Narrow:$imm)),
8601             (!cast<Instruction>(NAME # "v8i16_shift")
8602                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8603                 V128:$Rn, vecshiftR32Narrow:$imm)>;
8604   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8605                                                      vecshiftR64Narrow:$imm)),
8606             (!cast<Instruction>(NAME # "v4i32_shift")
8607                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8608                 V128:$Rn, vecshiftR64Narrow:$imm)>;
8611 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8612                                 SDPatternOperator OpNode> {
8613   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8614                                   V64, V64, vecshiftL8,
8615                                   asm, ".8b", ".8b",
8616                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8617                        (i32 vecshiftL8:$imm)))]> {
8618     bits<3> imm;
8619     let Inst{18-16} = imm;
8620   }
8622   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8623                                   V128, V128, vecshiftL8,
8624                                   asm, ".16b", ".16b",
8625              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8626                    (i32 vecshiftL8:$imm)))]> {
8627     bits<3> imm;
8628     let Inst{18-16} = imm;
8629   }
8631   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8632                                   V64, V64, vecshiftL16,
8633                                   asm, ".4h", ".4h",
8634               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8635                     (i32 vecshiftL16:$imm)))]> {
8636     bits<4> imm;
8637     let Inst{19-16} = imm;
8638   }
8640   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8641                                   V128, V128, vecshiftL16,
8642                                   asm, ".8h", ".8h",
8643             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8644                   (i32 vecshiftL16:$imm)))]> {
8645     bits<4> imm;
8646     let Inst{19-16} = imm;
8647   }
8649   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8650                                   V64, V64, vecshiftL32,
8651                                   asm, ".2s", ".2s",
8652               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8653                     (i32 vecshiftL32:$imm)))]> {
8654     bits<5> imm;
8655     let Inst{20-16} = imm;
8656   }
8658   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8659                                   V128, V128, vecshiftL32,
8660                                   asm, ".4s", ".4s",
8661             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8662                   (i32 vecshiftL32:$imm)))]> {
8663     bits<5> imm;
8664     let Inst{20-16} = imm;
8665   }
8667   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8668                                   V128, V128, vecshiftL64,
8669                                   asm, ".2d", ".2d",
8670             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8671                   (i32 vecshiftL64:$imm)))]> {
8672     bits<6> imm;
8673     let Inst{21-16} = imm;
8674   }
8677 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8678                                 SDPatternOperator OpNode> {
8679   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8680                                   V64, V64, vecshiftR8,
8681                                   asm, ".8b", ".8b",
8682                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8683                        (i32 vecshiftR8:$imm)))]> {
8684     bits<3> imm;
8685     let Inst{18-16} = imm;
8686   }
8688   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8689                                   V128, V128, vecshiftR8,
8690                                   asm, ".16b", ".16b",
8691              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8692                    (i32 vecshiftR8:$imm)))]> {
8693     bits<3> imm;
8694     let Inst{18-16} = imm;
8695   }
8697   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8698                                   V64, V64, vecshiftR16,
8699                                   asm, ".4h", ".4h",
8700               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8701                     (i32 vecshiftR16:$imm)))]> {
8702     bits<4> imm;
8703     let Inst{19-16} = imm;
8704   }
8706   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8707                                   V128, V128, vecshiftR16,
8708                                   asm, ".8h", ".8h",
8709             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8710                   (i32 vecshiftR16:$imm)))]> {
8711     bits<4> imm;
8712     let Inst{19-16} = imm;
8713   }
8715   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8716                                   V64, V64, vecshiftR32,
8717                                   asm, ".2s", ".2s",
8718               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8719                     (i32 vecshiftR32:$imm)))]> {
8720     bits<5> imm;
8721     let Inst{20-16} = imm;
8722   }
8724   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8725                                   V128, V128, vecshiftR32,
8726                                   asm, ".4s", ".4s",
8727             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8728                   (i32 vecshiftR32:$imm)))]> {
8729     bits<5> imm;
8730     let Inst{20-16} = imm;
8731   }
8733   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8734                                   V128, V128, vecshiftR64,
8735                                   asm, ".2d", ".2d",
8736             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8737                   (i32 vecshiftR64:$imm)))]> {
8738     bits<6> imm;
8739     let Inst{21-16} = imm;
8740   }
8743 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8744 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8745                                     SDPatternOperator OpNode = null_frag> {
8746   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8747                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8748                  [(set (v8i8 V64:$dst),
8749                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8750                            (i32 vecshiftR8:$imm)))]> {
8751     bits<3> imm;
8752     let Inst{18-16} = imm;
8753   }
8755   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8756                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8757              [(set (v16i8 V128:$dst),
8758                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8759                        (i32 vecshiftR8:$imm)))]> {
8760     bits<3> imm;
8761     let Inst{18-16} = imm;
8762   }
8764   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8765                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8766               [(set (v4i16 V64:$dst),
8767                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8768                         (i32 vecshiftR16:$imm)))]> {
8769     bits<4> imm;
8770     let Inst{19-16} = imm;
8771   }
8773   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8774                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8775             [(set (v8i16 V128:$dst),
8776               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8777                       (i32 vecshiftR16:$imm)))]> {
8778     bits<4> imm;
8779     let Inst{19-16} = imm;
8780   }
8782   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8783                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8784               [(set (v2i32 V64:$dst),
8785                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8786                         (i32 vecshiftR32:$imm)))]> {
8787     bits<5> imm;
8788     let Inst{20-16} = imm;
8789   }
8791   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8792                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8793             [(set (v4i32 V128:$dst),
8794               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8795                       (i32 vecshiftR32:$imm)))]> {
8796     bits<5> imm;
8797     let Inst{20-16} = imm;
8798   }
8800   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8801                                   V128, V128, vecshiftR64,
8802                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8803               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8804                       (i32 vecshiftR64:$imm)))]> {
8805     bits<6> imm;
8806     let Inst{21-16} = imm;
8807   }
8810 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8811                                     SDPatternOperator OpNode = null_frag> {
8812   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8813                                   V64, V64, vecshiftL8,
8814                                   asm, ".8b", ".8b",
8815                     [(set (v8i8 V64:$dst),
8816                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8817                                   (i32 vecshiftL8:$imm)))]> {
8818     bits<3> imm;
8819     let Inst{18-16} = imm;
8820   }
8822   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8823                                   V128, V128, vecshiftL8,
8824                                   asm, ".16b", ".16b",
8825                     [(set (v16i8 V128:$dst),
8826                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8827                                   (i32 vecshiftL8:$imm)))]> {
8828     bits<3> imm;
8829     let Inst{18-16} = imm;
8830   }
8832   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8833                                   V64, V64, vecshiftL16,
8834                                   asm, ".4h", ".4h",
8835                     [(set (v4i16 V64:$dst),
8836                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8837                                    (i32 vecshiftL16:$imm)))]> {
8838     bits<4> imm;
8839     let Inst{19-16} = imm;
8840   }
8842   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8843                                   V128, V128, vecshiftL16,
8844                                   asm, ".8h", ".8h",
8845                     [(set (v8i16 V128:$dst),
8846                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8847                                   (i32 vecshiftL16:$imm)))]> {
8848     bits<4> imm;
8849     let Inst{19-16} = imm;
8850   }
8852   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8853                                   V64, V64, vecshiftL32,
8854                                   asm, ".2s", ".2s",
8855                     [(set (v2i32 V64:$dst),
8856                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8857                                   (i32 vecshiftL32:$imm)))]> {
8858     bits<5> imm;
8859     let Inst{20-16} = imm;
8860   }
8862   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8863                                   V128, V128, vecshiftL32,
8864                                   asm, ".4s", ".4s",
8865                     [(set (v4i32 V128:$dst),
8866                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8867                                   (i32 vecshiftL32:$imm)))]> {
8868     bits<5> imm;
8869     let Inst{20-16} = imm;
8870   }
8872   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8873                                   V128, V128, vecshiftL64,
8874                                   asm, ".2d", ".2d",
8875                     [(set (v2i64 V128:$dst),
8876                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8877                                   (i32 vecshiftL64:$imm)))]> {
8878     bits<6> imm;
8879     let Inst{21-16} = imm;
8880   }
8883 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8884                                    SDPatternOperator OpNode> {
8885   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8886                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8887       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8888     bits<3> imm;
8889     let Inst{18-16} = imm;
8890   }
8892   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8893                                   V128, V128, vecshiftL8,
8894                                   asm#"2", ".8h", ".16b",
8895       [(set (v8i16 V128:$Rd),
8896             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8897     bits<3> imm;
8898     let Inst{18-16} = imm;
8899   }
8901   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8902                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8903       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8904     bits<4> imm;
8905     let Inst{19-16} = imm;
8906   }
8908   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8909                                   V128, V128, vecshiftL16,
8910                                   asm#"2", ".4s", ".8h",
8911       [(set (v4i32 V128:$Rd),
8912             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8914     bits<4> imm;
8915     let Inst{19-16} = imm;
8916   }
8918   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8919                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8920       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8921     bits<5> imm;
8922     let Inst{20-16} = imm;
8923   }
8925   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8926                                   V128, V128, vecshiftL32,
8927                                   asm#"2", ".2d", ".4s",
8928       [(set (v2i64 V128:$Rd),
8929             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8930     bits<5> imm;
8931     let Inst{20-16} = imm;
8932   }
8936 //---
8937 // Vector load/store
8938 //---
8939 // SIMD ldX/stX no-index memory references don't allow the optional
8940 // ", #0" constant and handle post-indexing explicitly, so we use
8941 // a more specialized parse method for them. Otherwise, it's the same as
8942 // the general GPR64sp handling.
8944 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8945                    string asm, dag oops, dag iops, list<dag> pattern>
8946   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8947   bits<5> Vt;
8948   bits<5> Rn;
8949   let Inst{31} = 0;
8950   let Inst{30} = Q;
8951   let Inst{29-23} = 0b0011000;
8952   let Inst{22} = L;
8953   let Inst{21-16} = 0b000000;
8954   let Inst{15-12} = opcode;
8955   let Inst{11-10} = size;
8956   let Inst{9-5} = Rn;
8957   let Inst{4-0} = Vt;
8960 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8961                        string asm, dag oops, dag iops>
8962   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8963   bits<5> Vt;
8964   bits<5> Rn;
8965   bits<5> Xm;
8966   let Inst{31} = 0;
8967   let Inst{30} = Q;
8968   let Inst{29-23} = 0b0011001;
8969   let Inst{22} = L;
8970   let Inst{21} = 0;
8971   let Inst{20-16} = Xm;
8972   let Inst{15-12} = opcode;
8973   let Inst{11-10} = size;
8974   let Inst{9-5} = Rn;
8975   let Inst{4-0} = Vt;
8978 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8979 // register post-index addressing from the zero register.
8980 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
8981                            int Offset, int Size> {
8982   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8983   //      "ld1\t$Vt, [$Rn], #16"
8984   // may get mapped to
8985   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8986   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8987                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8988                       GPR64sp:$Rn,
8989                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8990                       XZR), 1>;
8992   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8993   //      "ld1.8b\t$Vt, [$Rn], #16"
8994   // may get mapped to
8995   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8996   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8997                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8998                       GPR64sp:$Rn,
8999                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9000                       XZR), 0>;
9002   // E.g. "ld1.8b { v0, v1 }, [x1]"
9003   //      "ld1\t$Vt, [$Rn]"
9004   // may get mapped to
9005   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9006   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9007                   (!cast<Instruction>(BaseName # Count # "v" # layout)
9008                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9009                       GPR64sp:$Rn), 0>;
9011   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9012   //      "ld1\t$Vt, [$Rn], $Xm"
9013   // may get mapped to
9014   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9015   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9016                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9017                       GPR64sp:$Rn,
9018                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9019                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9022 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9023                        int Offset128, int Offset64, bits<4> opcode> {
9024   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9025     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9026                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9027                            (ins GPR64sp:$Rn), []>;
9028     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9029                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9030                            (ins GPR64sp:$Rn), []>;
9031     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9032                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9033                            (ins GPR64sp:$Rn), []>;
9034     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9035                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9036                            (ins GPR64sp:$Rn), []>;
9037     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9038                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9039                            (ins GPR64sp:$Rn), []>;
9040     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9041                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9042                            (ins GPR64sp:$Rn), []>;
9043     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9044                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9045                            (ins GPR64sp:$Rn), []>;
9048     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9049                        (outs GPR64sp:$wback,
9050                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
9051                        (ins GPR64sp:$Rn,
9052                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9053     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9054                        (outs GPR64sp:$wback,
9055                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
9056                        (ins GPR64sp:$Rn,
9057                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9058     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9059                        (outs GPR64sp:$wback,
9060                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
9061                        (ins GPR64sp:$Rn,
9062                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9063     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9064                        (outs GPR64sp:$wback,
9065                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
9066                        (ins GPR64sp:$Rn,
9067                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9068     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9069                        (outs GPR64sp:$wback,
9070                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
9071                        (ins GPR64sp:$Rn,
9072                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9073     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9074                        (outs GPR64sp:$wback,
9075                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
9076                        (ins GPR64sp:$Rn,
9077                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9078     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9079                        (outs GPR64sp:$wback,
9080                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
9081                        (ins GPR64sp:$Rn,
9082                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9083   }
9085   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9086   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9087   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9088   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9089   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9090   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9091   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9094 // Only ld1/st1 has a v1d version.
9095 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9096                        int Offset128, int Offset64, bits<4> opcode> {
9097   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9098     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9099                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9100                                  GPR64sp:$Rn), []>;
9101     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9102                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9103                                 GPR64sp:$Rn), []>;
9104     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9105                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9106                                 GPR64sp:$Rn), []>;
9107     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9108                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9109                                 GPR64sp:$Rn), []>;
9110     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9111                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9112                                 GPR64sp:$Rn), []>;
9113     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9114                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9115                                 GPR64sp:$Rn), []>;
9116     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9117                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9118                                 GPR64sp:$Rn), []>;
9120     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9121                        (outs GPR64sp:$wback),
9122                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9123                             GPR64sp:$Rn,
9124                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9125     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9126                        (outs GPR64sp:$wback),
9127                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9128                             GPR64sp:$Rn,
9129                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9130     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9131                        (outs GPR64sp:$wback),
9132                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9133                             GPR64sp:$Rn,
9134                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9135     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9136                        (outs GPR64sp:$wback),
9137                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9138                             GPR64sp:$Rn,
9139                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9140     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9141                        (outs GPR64sp:$wback),
9142                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9143                             GPR64sp:$Rn,
9144                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9145     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9146                        (outs GPR64sp:$wback),
9147                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9148                             GPR64sp:$Rn,
9149                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9150     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9151                        (outs GPR64sp:$wback),
9152                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9153                             GPR64sp:$Rn,
9154                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9155   }
9157   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9158   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9159   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9160   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9161   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9162   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9163   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9166 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9167                        int Offset128, int Offset64, bits<4> opcode>
9168   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9170   // LD1 instructions have extra "1d" variants.
9171   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9172     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9173                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9174                            (ins GPR64sp:$Rn), []>;
9176     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9177                        (outs GPR64sp:$wback,
9178                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
9179                        (ins GPR64sp:$Rn,
9180                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9181   }
9183   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9186 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9187                        int Offset128, int Offset64, bits<4> opcode>
9188   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9190   // ST1 instructions have extra "1d" variants.
9191   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9192     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9193                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9194                                 GPR64sp:$Rn), []>;
9196     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9197                        (outs GPR64sp:$wback),
9198                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9199                             GPR64sp:$Rn,
9200                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9201   }
9203   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9206 multiclass SIMDLd1Multiple<string asm> {
9207   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9208   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9209   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9210   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9213 multiclass SIMDSt1Multiple<string asm> {
9214   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9215   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9216   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9217   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9220 multiclass SIMDLd2Multiple<string asm> {
9221   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9224 multiclass SIMDSt2Multiple<string asm> {
9225   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9228 multiclass SIMDLd3Multiple<string asm> {
9229   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9232 multiclass SIMDSt3Multiple<string asm> {
9233   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9236 multiclass SIMDLd4Multiple<string asm> {
9237   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9240 multiclass SIMDSt4Multiple<string asm> {
9241   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9244 //---
9245 // AdvSIMD Load/store single-element
9246 //---
9248 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9249                          string asm, string operands, string cst,
9250                          dag oops, dag iops, list<dag> pattern>
9251   : I<oops, iops, asm, operands, cst, pattern> {
9252   bits<5> Vt;
9253   bits<5> Rn;
9254   let Inst{31} = 0;
9255   let Inst{29-24} = 0b001101;
9256   let Inst{22} = L;
9257   let Inst{21} = R;
9258   let Inst{15-13} = opcode;
9259   let Inst{9-5} = Rn;
9260   let Inst{4-0} = Vt;
9263 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9264                          string asm, string operands, string cst,
9265                          dag oops, dag iops, list<dag> pattern>
9266   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9267   bits<5> Vt;
9268   bits<5> Rn;
9269   let Inst{31} = 0;
9270   let Inst{29-24} = 0b001101;
9271   let Inst{22} = L;
9272   let Inst{21} = R;
9273   let Inst{15-13} = opcode;
9274   let Inst{9-5} = Rn;
9275   let Inst{4-0} = Vt;
9279 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9280 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9281                   DAGOperand listtype>
9282   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9283                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9284                        []> {
9285   let Inst{30} = Q;
9286   let Inst{23} = 0;
9287   let Inst{20-16} = 0b00000;
9288   let Inst{12} = S;
9289   let Inst{11-10} = size;
9291 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9292 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9293                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9294   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9295                        "$Rn = $wback",
9296                        (outs GPR64sp:$wback, listtype:$Vt),
9297                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9298   bits<5> Xm;
9299   let Inst{30} = Q;
9300   let Inst{23} = 1;
9301   let Inst{20-16} = Xm;
9302   let Inst{12} = S;
9303   let Inst{11-10} = size;
9306 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9307                           int Offset, int Size> {
9308   // E.g. "ld1r { v0.8b }, [x1], #1"
9309   //      "ld1r.8b\t$Vt, [$Rn], #1"
9310   // may get mapped to
9311   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9312   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9313                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9314                       GPR64sp:$Rn,
9315                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9316                       XZR), 1>;
9318   // E.g. "ld1r.8b { v0 }, [x1], #1"
9319   //      "ld1r.8b\t$Vt, [$Rn], #1"
9320   // may get mapped to
9321   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9322   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9323                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9324                       GPR64sp:$Rn,
9325                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9326                       XZR), 0>;
9328   // E.g. "ld1r.8b { v0 }, [x1]"
9329   //      "ld1r.8b\t$Vt, [$Rn]"
9330   // may get mapped to
9331   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9332   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9333                   (!cast<Instruction>(BaseName # "v" # layout)
9334                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9335                       GPR64sp:$Rn), 0>;
9337   // E.g. "ld1r.8b { v0 }, [x1], x2"
9338   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9339   // may get mapped to
9340   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9341   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9342                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9343                       GPR64sp:$Rn,
9344                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9345                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9348 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9349   int Offset1, int Offset2, int Offset4, int Offset8> {
9350   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9351                         !cast<DAGOperand>("VecList" # Count # "8b")>;
9352   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9353                         !cast<DAGOperand>("VecList" # Count #"16b")>;
9354   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9355                         !cast<DAGOperand>("VecList" # Count #"4h")>;
9356   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9357                         !cast<DAGOperand>("VecList" # Count #"8h")>;
9358   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9359                         !cast<DAGOperand>("VecList" # Count #"2s")>;
9360   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9361                         !cast<DAGOperand>("VecList" # Count #"4s")>;
9362   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9363                         !cast<DAGOperand>("VecList" # Count #"1d")>;
9364   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9365                         !cast<DAGOperand>("VecList" # Count #"2d")>;
9367   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9368                                  !cast<DAGOperand>("VecList" # Count # "8b"),
9369                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9370   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9371                                  !cast<DAGOperand>("VecList" # Count # "16b"),
9372                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9373   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9374                                  !cast<DAGOperand>("VecList" # Count # "4h"),
9375                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9376   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9377                                  !cast<DAGOperand>("VecList" # Count # "8h"),
9378                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9379   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9380                                  !cast<DAGOperand>("VecList" # Count # "2s"),
9381                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9382   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9383                                  !cast<DAGOperand>("VecList" # Count # "4s"),
9384                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9385   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9386                                  !cast<DAGOperand>("VecList" # Count # "1d"),
9387                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9388   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9389                                  !cast<DAGOperand>("VecList" # Count # "2d"),
9390                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9392   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9393   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9394   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9395   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9396   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9397   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9398   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9399   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9402 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9403                       dag oops, dag iops, list<dag> pattern>
9404   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9405                        pattern> {
9406   // idx encoded in Q:S:size fields.
9407   bits<4> idx;
9408   let Inst{30} = idx{3};
9409   let Inst{23} = 0;
9410   let Inst{20-16} = 0b00000;
9411   let Inst{12} = idx{2};
9412   let Inst{11-10} = idx{1-0};
9414 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9415                       dag oops, dag iops, list<dag> pattern>
9416   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9417                            oops, iops, pattern> {
9418   // idx encoded in Q:S:size fields.
9419   bits<4> idx;
9420   let Inst{30} = idx{3};
9421   let Inst{23} = 0;
9422   let Inst{20-16} = 0b00000;
9423   let Inst{12} = idx{2};
9424   let Inst{11-10} = idx{1-0};
9426 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9427                           dag oops, dag iops>
9428   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9429                        "$Rn = $wback", oops, iops, []> {
9430   // idx encoded in Q:S:size fields.
9431   bits<4> idx;
9432   bits<5> Xm;
9433   let Inst{30} = idx{3};
9434   let Inst{23} = 1;
9435   let Inst{20-16} = Xm;
9436   let Inst{12} = idx{2};
9437   let Inst{11-10} = idx{1-0};
9439 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9440                           dag oops, dag iops>
9441   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9442                            "$Rn = $wback", oops, iops, []> {
9443   // idx encoded in Q:S:size fields.
9444   bits<4> idx;
9445   bits<5> Xm;
9446   let Inst{30} = idx{3};
9447   let Inst{23} = 1;
9448   let Inst{20-16} = Xm;
9449   let Inst{12} = idx{2};
9450   let Inst{11-10} = idx{1-0};
9453 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9454                       dag oops, dag iops, list<dag> pattern>
9455   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9456                        pattern> {
9457   // idx encoded in Q:S:size<1> fields.
9458   bits<3> idx;
9459   let Inst{30} = idx{2};
9460   let Inst{23} = 0;
9461   let Inst{20-16} = 0b00000;
9462   let Inst{12} = idx{1};
9463   let Inst{11} = idx{0};
9464   let Inst{10} = size;
9466 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9467                       dag oops, dag iops, list<dag> pattern>
9468   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9469                            oops, iops, pattern> {
9470   // idx encoded in Q:S:size<1> fields.
9471   bits<3> idx;
9472   let Inst{30} = idx{2};
9473   let Inst{23} = 0;
9474   let Inst{20-16} = 0b00000;
9475   let Inst{12} = idx{1};
9476   let Inst{11} = idx{0};
9477   let Inst{10} = size;
9480 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9481                           dag oops, dag iops>
9482   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9483                        "$Rn = $wback", oops, iops, []> {
9484   // idx encoded in Q:S:size<1> fields.
9485   bits<3> idx;
9486   bits<5> Xm;
9487   let Inst{30} = idx{2};
9488   let Inst{23} = 1;
9489   let Inst{20-16} = Xm;
9490   let Inst{12} = idx{1};
9491   let Inst{11} = idx{0};
9492   let Inst{10} = size;
9494 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9495                           dag oops, dag iops>
9496   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9497                            "$Rn = $wback", oops, iops, []> {
9498   // idx encoded in Q:S:size<1> fields.
9499   bits<3> idx;
9500   bits<5> Xm;
9501   let Inst{30} = idx{2};
9502   let Inst{23} = 1;
9503   let Inst{20-16} = Xm;
9504   let Inst{12} = idx{1};
9505   let Inst{11} = idx{0};
9506   let Inst{10} = size;
9508 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9509                       dag oops, dag iops, list<dag> pattern>
9510   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9511                        pattern> {
9512   // idx encoded in Q:S fields.
9513   bits<2> idx;
9514   let Inst{30} = idx{1};
9515   let Inst{23} = 0;
9516   let Inst{20-16} = 0b00000;
9517   let Inst{12} = idx{0};
9518   let Inst{11-10} = size;
9520 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9521                       dag oops, dag iops, list<dag> pattern>
9522   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9523                            oops, iops, pattern> {
9524   // idx encoded in Q:S fields.
9525   bits<2> idx;
9526   let Inst{30} = idx{1};
9527   let Inst{23} = 0;
9528   let Inst{20-16} = 0b00000;
9529   let Inst{12} = idx{0};
9530   let Inst{11-10} = size;
9532 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9533                           string asm, dag oops, dag iops>
9534   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9535                        "$Rn = $wback", oops, iops, []> {
9536   // idx encoded in Q:S fields.
9537   bits<2> idx;
9538   bits<5> Xm;
9539   let Inst{30} = idx{1};
9540   let Inst{23} = 1;
9541   let Inst{20-16} = Xm;
9542   let Inst{12} = idx{0};
9543   let Inst{11-10} = size;
9545 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9546                           string asm, dag oops, dag iops>
9547   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9548                            "$Rn = $wback", oops, iops, []> {
9549   // idx encoded in Q:S fields.
9550   bits<2> idx;
9551   bits<5> Xm;
9552   let Inst{30} = idx{1};
9553   let Inst{23} = 1;
9554   let Inst{20-16} = Xm;
9555   let Inst{12} = idx{0};
9556   let Inst{11-10} = size;
9558 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9559                       dag oops, dag iops, list<dag> pattern>
9560   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9561                        pattern> {
9562   // idx encoded in Q field.
9563   bits<1> idx;
9564   let Inst{30} = idx;
9565   let Inst{23} = 0;
9566   let Inst{20-16} = 0b00000;
9567   let Inst{12} = 0;
9568   let Inst{11-10} = size;
9570 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9571                       dag oops, dag iops, list<dag> pattern>
9572   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9573                            oops, iops, pattern> {
9574   // idx encoded in Q field.
9575   bits<1> idx;
9576   let Inst{30} = idx;
9577   let Inst{23} = 0;
9578   let Inst{20-16} = 0b00000;
9579   let Inst{12} = 0;
9580   let Inst{11-10} = size;
9582 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9583                           string asm, dag oops, dag iops>
9584   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9585                        "$Rn = $wback", oops, iops, []> {
9586   // idx encoded in Q field.
9587   bits<1> idx;
9588   bits<5> Xm;
9589   let Inst{30} = idx;
9590   let Inst{23} = 1;
9591   let Inst{20-16} = Xm;
9592   let Inst{12} = 0;
9593   let Inst{11-10} = size;
9595 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9596                           string asm, dag oops, dag iops>
9597   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9598                            "$Rn = $wback", oops, iops, []> {
9599   // idx encoded in Q field.
9600   bits<1> idx;
9601   bits<5> Xm;
9602   let Inst{30} = idx;
9603   let Inst{23} = 1;
9604   let Inst{20-16} = Xm;
9605   let Inst{12} = 0;
9606   let Inst{11-10} = size;
9609 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9610 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9611                          RegisterOperand listtype,
9612                          RegisterOperand GPR64pi> {
9613   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9614                            (outs listtype:$dst),
9615                            (ins listtype:$Vt, VectorIndexB:$idx,
9616                                 GPR64sp:$Rn), []>;
9618   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9619                             (outs GPR64sp:$wback, listtype:$dst),
9620                             (ins listtype:$Vt, VectorIndexB:$idx,
9621                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9623 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9624 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9625                          RegisterOperand listtype,
9626                          RegisterOperand GPR64pi> {
9627   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9628                             (outs listtype:$dst),
9629                             (ins listtype:$Vt, VectorIndexH:$idx,
9630                                  GPR64sp:$Rn), []>;
9632   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9633                             (outs GPR64sp:$wback, listtype:$dst),
9634                             (ins listtype:$Vt, VectorIndexH:$idx,
9635                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9637 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9638 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9639                          RegisterOperand listtype,
9640                          RegisterOperand GPR64pi> {
9641   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9642                             (outs listtype:$dst),
9643                             (ins listtype:$Vt, VectorIndexS:$idx,
9644                                  GPR64sp:$Rn), []>;
9646   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9647                             (outs GPR64sp:$wback, listtype:$dst),
9648                             (ins listtype:$Vt, VectorIndexS:$idx,
9649                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9651 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9652 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9653                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9654   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9655                             (outs listtype:$dst),
9656                             (ins listtype:$Vt, VectorIndexD:$idx,
9657                                  GPR64sp:$Rn), []>;
9659   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9660                             (outs GPR64sp:$wback, listtype:$dst),
9661                             (ins listtype:$Vt, VectorIndexD:$idx,
9662                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9664 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9665 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9666                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9667   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9668                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9669                                         GPR64sp:$Rn), []>;
9671   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9672                                     (outs GPR64sp:$wback),
9673                                     (ins listtype:$Vt, VectorIndexB:$idx,
9674                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
9676 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9677 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9678                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9679   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9680                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9681                                          GPR64sp:$Rn), []>;
9683   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9684                             (outs GPR64sp:$wback),
9685                             (ins listtype:$Vt, VectorIndexH:$idx,
9686                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9688 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9689 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9690                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9691   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9692                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9693                                          GPR64sp:$Rn), []>;
9695   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9696                             (outs GPR64sp:$wback),
9697                             (ins listtype:$Vt, VectorIndexS:$idx,
9698                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9700 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9701 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9702                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9703   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9704                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9705                                          GPR64sp:$Rn), []>;
9707   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9708                             (outs GPR64sp:$wback),
9709                             (ins listtype:$Vt, VectorIndexD:$idx,
9710                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9713 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9714                                  string Count, int Offset, Operand idxtype> {
9715   // E.g. "ld1 { v0.8b }[0], [x1], #1"
9716   //      "ld1\t$Vt, [$Rn], #1"
9717   // may get mapped to
9718   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9719   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9720                   (!cast<Instruction>(NAME # Type  # "_POST")
9721                       GPR64sp:$Rn,
9722                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9723                       idxtype:$idx, XZR), 1>;
9725   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9726   //      "ld1.8b\t$Vt, [$Rn], #1"
9727   // may get mapped to
9728   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9729   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9730                   (!cast<Instruction>(NAME # Type # "_POST")
9731                       GPR64sp:$Rn,
9732                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9733                       idxtype:$idx, XZR), 0>;
9735   // E.g. "ld1.8b { v0 }[0], [x1]"
9736   //      "ld1.8b\t$Vt, [$Rn]"
9737   // may get mapped to
9738   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9739   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9740                       (!cast<Instruction>(NAME # Type)
9741                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9742                          idxtype:$idx, GPR64sp:$Rn), 0>;
9744   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9745   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9746   // may get mapped to
9747   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9748   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9749                       (!cast<Instruction>(NAME # Type # "_POST")
9750                          GPR64sp:$Rn,
9751                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9752                          idxtype:$idx,
9753                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9756 multiclass SIMDLdSt1SingleAliases<string asm> {
9757   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9758   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9759   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9760   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9763 multiclass SIMDLdSt2SingleAliases<string asm> {
9764   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9765   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9766   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9767   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9770 multiclass SIMDLdSt3SingleAliases<string asm> {
9771   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9772   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9773   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9774   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9777 multiclass SIMDLdSt4SingleAliases<string asm> {
9778   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9779   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9780   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9781   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9783 } // end of 'let Predicates = [HasNEON]'
9785 //----------------------------------------------------------------------------
9786 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9787 //----------------------------------------------------------------------------
9789 let Predicates = [HasNEON, HasRDM] in {
9791 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9792                                     RegisterOperand regtype, string asm,
9793                                     string kind, list<dag> pattern>
9794   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9795                                 pattern> {
9797 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9798                                              SDPatternOperator Accum> {
9799   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9800     [(set (v4i16 V64:$dst),
9801           (Accum (v4i16 V64:$Rd),
9802                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9803                                                    (v4i16 V64:$Rm)))))]>;
9804   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9805     [(set (v8i16 V128:$dst),
9806           (Accum (v8i16 V128:$Rd),
9807                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9808                                                    (v8i16 V128:$Rm)))))]>;
9809   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9810     [(set (v2i32 V64:$dst),
9811           (Accum (v2i32 V64:$Rd),
9812                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9813                                                    (v2i32 V64:$Rm)))))]>;
9814   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9815     [(set (v4i32 V128:$dst),
9816           (Accum (v4i32 V128:$Rd),
9817                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9818                                                    (v4i32 V128:$Rm)))))]>;
9821 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9822                                      SDPatternOperator Accum> {
9823   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9824                                           V64, V64, V128_lo, VectorIndexH,
9825                                           asm, ".4h", ".4h", ".4h", ".h",
9826     [(set (v4i16 V64:$dst),
9827           (Accum (v4i16 V64:$Rd),
9828                  (v4i16 (int_aarch64_neon_sqrdmulh
9829                           (v4i16 V64:$Rn),
9830                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9831                                                     VectorIndexH:$idx))))))]> {
9832     bits<3> idx;
9833     let Inst{11} = idx{2};
9834     let Inst{21} = idx{1};
9835     let Inst{20} = idx{0};
9836   }
9838   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9839                                           V128, V128, V128_lo, VectorIndexH,
9840                                           asm, ".8h", ".8h", ".8h", ".h",
9841     [(set (v8i16 V128:$dst),
9842           (Accum (v8i16 V128:$Rd),
9843                  (v8i16 (int_aarch64_neon_sqrdmulh
9844                           (v8i16 V128:$Rn),
9845                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9846                                                    VectorIndexH:$idx))))))]> {
9847     bits<3> idx;
9848     let Inst{11} = idx{2};
9849     let Inst{21} = idx{1};
9850     let Inst{20} = idx{0};
9851   }
9853   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9854                                           V64, V64, V128, VectorIndexS,
9855                                           asm, ".2s", ".2s", ".2s", ".s",
9856     [(set (v2i32 V64:$dst),
9857         (Accum (v2i32 V64:$Rd),
9858                (v2i32 (int_aarch64_neon_sqrdmulh
9859                         (v2i32 V64:$Rn),
9860                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9861                                                  VectorIndexS:$idx))))))]> {
9862     bits<2> idx;
9863     let Inst{11} = idx{1};
9864     let Inst{21} = idx{0};
9865   }
9867   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9868   // an intermediate EXTRACT_SUBREG would be untyped.
9869   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9870   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9871   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9872                        (i32 (vector_extract
9873                                (v4i32 (insert_subvector
9874                                        (undef),
9875                                         (v2i32 (int_aarch64_neon_sqrdmulh
9876                                                  (v2i32 V64:$Rn),
9877                                                  (v2i32 (AArch64duplane32
9878                                                           (v4i32 V128:$Rm),
9879                                                           VectorIndexS:$idx)))),
9880                                       (i32 0))),
9881                                (i64 0))))),
9882             (EXTRACT_SUBREG
9883                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9884                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9885                                                 FPR32Op:$Rd,
9886                                                 ssub)),
9887                           V64:$Rn,
9888                           V128:$Rm,
9889                           VectorIndexS:$idx)),
9890                 ssub)>;
9892   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9893                                           V128, V128, V128, VectorIndexS,
9894                                           asm, ".4s", ".4s", ".4s", ".s",
9895     [(set (v4i32 V128:$dst),
9896           (Accum (v4i32 V128:$Rd),
9897                  (v4i32 (int_aarch64_neon_sqrdmulh
9898                           (v4i32 V128:$Rn),
9899                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9900                                                    VectorIndexS:$idx))))))]> {
9901     bits<2> idx;
9902     let Inst{11} = idx{1};
9903     let Inst{21} = idx{0};
9904   }
9906   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9907   // an intermediate EXTRACT_SUBREG would be untyped.
9908   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9909                         (i32 (vector_extract
9910                                (v4i32 (int_aarch64_neon_sqrdmulh
9911                                         (v4i32 V128:$Rn),
9912                                         (v4i32 (AArch64duplane32
9913                                                  (v4i32 V128:$Rm),
9914                                                  VectorIndexS:$idx)))),
9915                                (i64 0))))),
9916             (EXTRACT_SUBREG
9917                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9918                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9919                                                FPR32Op:$Rd,
9920                                                ssub)),
9921                          V128:$Rn,
9922                          V128:$Rm,
9923                          VectorIndexS:$idx)),
9924                 ssub)>;
9926   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9927                                         FPR16Op, FPR16Op, V128_lo,
9928                                         VectorIndexH, asm, ".h", "", "", ".h",
9929                                         []> {
9930     bits<3> idx;
9931     let Inst{11} = idx{2};
9932     let Inst{21} = idx{1};
9933     let Inst{20} = idx{0};
9934   }
9936   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9937                                         FPR32Op, FPR32Op, V128, VectorIndexS,
9938                                         asm, ".s", "", "", ".s",
9939     [(set (i32 FPR32Op:$dst),
9940           (Accum (i32 FPR32Op:$Rd),
9941                  (i32 (int_aarch64_neon_sqrdmulh
9942                         (i32 FPR32Op:$Rn),
9943                         (i32 (vector_extract (v4i32 V128:$Rm),
9944                                              VectorIndexS:$idx))))))]> {
9945     bits<2> idx;
9946     let Inst{11} = idx{1};
9947     let Inst{21} = idx{0};
9948   }
9950 } // let Predicates = [HasNeon, HasRDM]
9952 //----------------------------------------------------------------------------
9953 // ARMv8.3 Complex ADD/MLA instructions
9954 //----------------------------------------------------------------------------
9956 class ComplexRotationOperand<int Angle, int Remainder, string Type>
9957   : AsmOperandClass {
9958   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
9959   let DiagnosticType = "InvalidComplexRotation" # Type;
9960   let Name = "ComplexRotation" # Type;
9962 def complexrotateop : Operand<i32> {
9963   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
9964   let PrintMethod = "printComplexRotationOp<90, 0>";
9966 def complexrotateopodd : Operand<i32> {
9967   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
9968   let PrintMethod = "printComplexRotationOp<180, 90>";
9971 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9972 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
9973                                      RegisterOperand regtype, Operand rottype,
9974                                      string asm, string kind, list<dag> pattern>
9975   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9976       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9977       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
9978     Sched<[WriteV]> {
9979   bits<5> Rd;
9980   bits<5> Rn;
9981   bits<5> Rm;
9982   bits<1> rot;
9983   let Inst{31}    = 0;
9984   let Inst{30}    = Q;
9985   let Inst{29}    = U;
9986   let Inst{28-24} = 0b01110;
9987   let Inst{23-22} = size;
9988   let Inst{21}    = 0;
9989   let Inst{20-16} = Rm;
9990   let Inst{15-13} = opcode;
9991   // Non-tied version (FCADD) only has one rotation bit
9992   let Inst{12}    = rot;
9993   let Inst{11}    = 0;
9994   let Inst{10}    = 1;
9995   let Inst{9-5}   = Rn;
9996   let Inst{4-0}   = Rd;
9999 //8.3 CompNum - Floating-point complex number support
10000 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10001                                           string asm, SDPatternOperator OpNode>{
10002   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10003   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10004               asm, ".4h",
10005               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10006                                               (v4f16 V64:$Rn),
10007                                               (v4f16 V64:$Rm),
10008                                               (rottype i32:$rot)))]>;
10010   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10011               asm, ".8h",
10012               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10013                                                (v8f16 V128:$Rn),
10014                                                (v8f16 V128:$Rm),
10015                                                (rottype i32:$rot)))]>;
10016   }
10018   let Predicates = [HasComplxNum, HasNEON] in {
10019   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10020               asm, ".2s",
10021               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10022                                               (v2f32 V64:$Rn),
10023                                               (v2f32 V64:$Rm),
10024                                               (rottype i32:$rot)))]>;
10026   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10027               asm, ".4s",
10028               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10029                                                (v4f32 V128:$Rn),
10030                                                (v4f32 V128:$Rm),
10031                                                (rottype i32:$rot)))]>;
10033   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10034               asm, ".2d",
10035               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10036                                                (v2f64 V128:$Rn),
10037                                                (v2f64 V128:$Rm),
10038                                                (rottype i32:$rot)))]>;
10039   }
10042 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10043 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10044                                          bits<3> opcode,
10045                                          RegisterOperand regtype,
10046                                          Operand rottype, string asm,
10047                                          string kind, list<dag> pattern>
10048   : I<(outs regtype:$dst),
10049       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10050       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10051       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10052     Sched<[WriteV]> {
10053   bits<5> Rd;
10054   bits<5> Rn;
10055   bits<5> Rm;
10056   bits<2> rot;
10057   let Inst{31}    = 0;
10058   let Inst{30}    = Q;
10059   let Inst{29}    = U;
10060   let Inst{28-24} = 0b01110;
10061   let Inst{23-22} = size;
10062   let Inst{21}    = 0;
10063   let Inst{20-16} = Rm;
10064   let Inst{15-13} = opcode;
10065   let Inst{12-11} = rot;
10066   let Inst{10}    = 1;
10067   let Inst{9-5}   = Rn;
10068   let Inst{4-0}   = Rd;
10071 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10072                                              Operand rottype, string asm,
10073                                              SDPatternOperator OpNode> {
10074   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10075   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10076               rottype, asm, ".4h",
10077               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10078                                               (v4f16 V64:$Rn),
10079                                               (v4f16 V64:$Rm),
10080                                               (rottype i32:$rot)))]>;
10082   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10083               rottype, asm, ".8h",
10084               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10085                                                (v8f16 V128:$Rn),
10086                                                (v8f16 V128:$Rm),
10087                                                (rottype i32:$rot)))]>;
10088   }
10090   let Predicates = [HasComplxNum, HasNEON] in {
10091   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10092               rottype, asm, ".2s",
10093               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10094                                               (v2f32 V64:$Rn),
10095                                               (v2f32 V64:$Rm),
10096                                               (rottype i32:$rot)))]>;
10098   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10099               rottype, asm, ".4s",
10100               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10101                                                (v4f32 V128:$Rn),
10102                                                (v4f32 V128:$Rm),
10103                                                (rottype i32:$rot)))]>;
10105   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10106               rottype, asm, ".2d",
10107               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10108                                                (v2f64 V128:$Rn),
10109                                                (v2f64 V128:$Rm),
10110                                                (rottype i32:$rot)))]>;
10111   }
10114 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10115 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10116                                  bit opc1, bit opc2, RegisterOperand dst_reg,
10117                                  RegisterOperand lhs_reg,
10118                                  RegisterOperand rhs_reg, Operand vec_idx,
10119                                  Operand rottype, string asm, string apple_kind,
10120                                  string dst_kind, string lhs_kind,
10121                                  string rhs_kind, list<dag> pattern>
10122   : I<(outs dst_reg:$dst),
10123       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10124       asm,
10125       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10126       "$idx, $rot" # "|" # apple_kind #
10127       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10128     Sched<[WriteV]> {
10129   bits<5> Rd;
10130   bits<5> Rn;
10131   bits<5> Rm;
10132   bits<2> rot;
10134   let Inst{31}    = 0;
10135   let Inst{30}    = Q;
10136   let Inst{29}    = U;
10137   let Inst{28}    = Scalar;
10138   let Inst{27-24} = 0b1111;
10139   let Inst{23-22} = size;
10140   // Bit 21 must be set by the derived class.
10141   let Inst{20-16} = Rm;
10142   let Inst{15}    = opc1;
10143   let Inst{14-13} = rot;
10144   let Inst{12}    = opc2;
10145   // Bit 11 must be set by the derived class.
10146   let Inst{10}    = 0;
10147   let Inst{9-5}   = Rn;
10148   let Inst{4-0}   = Rd;
10151 // The complex instructions index by pairs of elements, so the VectorIndexes
10152 // don't match the lane types, and the index bits are different to the other
10153 // classes.
10154 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10155                                      string asm, SDPatternOperator OpNode> {
10156   let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10157   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10158                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10159                       ".4h", ".h", []> {
10160     bits<1> idx;
10161     let Inst{11} = 0;
10162     let Inst{21} = idx{0};
10163   }
10165   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10166                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10167                       ".8h", ".8h", ".h", []> {
10168     bits<2> idx;
10169     let Inst{11} = idx{1};
10170     let Inst{21} = idx{0};
10171   }
10172   } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10174   let Predicates = [HasComplxNum, HasNEON] in {
10175   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10176                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10177                       ".4s", ".4s", ".s", []> {
10178     bits<1> idx;
10179     let Inst{11} = idx{0};
10180     let Inst{21} = 0;
10181   }
10182   } // Predicates = [HasComplxNum, HasNEON]
10185 //----------------------------------------------------------------------------
10186 // Crypto extensions
10187 //----------------------------------------------------------------------------
10189 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10190 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10191               list<dag> pat>
10192   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10193     Sched<[WriteV]>{
10194   bits<5> Rd;
10195   bits<5> Rn;
10196   let Inst{31-16} = 0b0100111000101000;
10197   let Inst{15-12} = opc;
10198   let Inst{11-10} = 0b10;
10199   let Inst{9-5}   = Rn;
10200   let Inst{4-0}   = Rd;
10203 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10204   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10205             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10207 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10208   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10209             "$Rd = $dst",
10210             [(set (v16i8 V128:$dst),
10211                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10213 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10214 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10215                      dag oops, dag iops, list<dag> pat>
10216   : I<oops, iops, asm,
10217       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10218       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10219     Sched<[WriteV]>{
10220   bits<5> Rd;
10221   bits<5> Rn;
10222   bits<5> Rm;
10223   let Inst{31-21} = 0b01011110000;
10224   let Inst{20-16} = Rm;
10225   let Inst{15}    = 0;
10226   let Inst{14-12} = opc;
10227   let Inst{11-10} = 0b00;
10228   let Inst{9-5}   = Rn;
10229   let Inst{4-0}   = Rd;
10232 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10233   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10234                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10235                    [(set (v4i32 FPR128:$dst),
10236                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10237                                  (v4i32 V128:$Rm)))]>;
10239 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10240   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10241                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
10242                    [(set (v4i32 V128:$dst),
10243                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10244                                  (v4i32 V128:$Rm)))]>;
10246 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10247   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10248                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10249                    [(set (v4i32 FPR128:$dst),
10250                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10251                                  (v4i32 V128:$Rm)))]>;
10253 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10254 class SHA2OpInst<bits<4> opc, string asm, string kind,
10255                  string cstr, dag oops, dag iops,
10256                  list<dag> pat>
10257   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10258                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10259     Sched<[WriteV]>{
10260   bits<5> Rd;
10261   bits<5> Rn;
10262   let Inst{31-16} = 0b0101111000101000;
10263   let Inst{15-12} = opc;
10264   let Inst{11-10} = 0b10;
10265   let Inst{9-5}   = Rn;
10266   let Inst{4-0}   = Rd;
10269 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10270   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10271                (ins V128:$Rd, V128:$Rn),
10272                [(set (v4i32 V128:$dst),
10273                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10275 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10276   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10277                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10279 // Armv8.2-A Crypto extensions
10280 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10281                     list<dag> pattern>
10282   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10283   bits<5> Vd;
10284   bits<5> Vn;
10285   let Inst{31-25} = 0b1100111;
10286   let Inst{9-5}   = Vn;
10287   let Inst{4-0}   = Vd;
10290 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10291   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10292                   "$Vm = $Vd", []> {
10293   let Inst{31-25} = 0b1100111;
10294   let Inst{24-21} = 0b0110;
10295   let Inst{20-15} = 0b000001;
10296   let Inst{14}    = op0;
10297   let Inst{13-12} = 0b00;
10298   let Inst{11-10} = op1;
10300 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10301   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10302 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10303   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10305 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10306                 string asmops, string cst>
10307   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10308   bits<5> Vm;
10309   let Inst{24-21} = 0b0011;
10310   let Inst{20-16} = Vm;
10311   let Inst{15}    = 0b1;
10312   let Inst{14}    = op0;
10313   let Inst{13-12} = 0b00;
10314   let Inst{11-10} = op1;
10316 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10317   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10318               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10319 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10320   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10321               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10322 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10323   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10324               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10325 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10326   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10327               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10328 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10329   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10330               asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10332 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10333   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10334                   asmops, "", []> {
10335   bits<5> Vm;
10336   bits<5> Va;
10337   let Inst{24-23} = 0b00;
10338   let Inst{22-21} = op0;
10339   let Inst{20-16} = Vm;
10340   let Inst{15}    = 0b0;
10341   let Inst{14-10} = Va;
10343 class CryptoRRRR_16B<bits<2>op0, string asm>
10344  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10346 class CryptoRRRR_4S<bits<2>op0, string asm>
10347  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10350 class CryptoRRRi6<string asm>
10351   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10352                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10353   bits<6> imm;
10354   bits<5> Vm;
10355   let Inst{24-21} = 0b0100;
10356   let Inst{20-16} = Vm;
10357   let Inst{15-10} = imm;
10358   let Inst{9-5}   = Vn;
10359   let Inst{4-0}   = Vd;
10362 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10363   : BaseCryptoV82<(outs V128:$Vdst),
10364                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10365                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10366   bits<2> imm;
10367   bits<5> Vm;
10368   let Inst{24-21} = 0b0010;
10369   let Inst{20-16} = Vm;
10370   let Inst{15}    = 0b1;
10371   let Inst{14}    = op0;
10372   let Inst{13-12} = imm;
10373   let Inst{11-10} = op1;
10376 //----------------------------------------------------------------------------
10377 // v8.1 atomic instructions extension:
10378 // * CAS
10379 // * CASP
10380 // * SWP
10381 // * LDOPregister<OP>, and aliases STOPregister<OP>
10383 // Instruction encodings:
10385 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10386 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10387 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10388 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10389 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10390 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10392 // Instruction syntax:
10394 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10395 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10396 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10397 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10398 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10399 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10400 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10401 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10402 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10403 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10405 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10406 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10407                       string cstr, list<dag> pattern>
10408       : I<oops, iops, asm, operands, cstr, pattern> {
10409   bits<2> Sz;
10410   bit NP;
10411   bit Acq;
10412   bit Rel;
10413   bits<5> Rs;
10414   bits<5> Rn;
10415   bits<5> Rt;
10416   let Inst{31-30} = Sz;
10417   let Inst{29-24} = 0b001000;
10418   let Inst{23} = NP;
10419   let Inst{22} = Acq;
10420   let Inst{21} = 0b1;
10421   let Inst{20-16} = Rs;
10422   let Inst{15} = Rel;
10423   let Inst{14-10} = 0b11111;
10424   let Inst{9-5} = Rn;
10425   let Inst{4-0} = Rt;
10426   let Predicates = [HasLSE];
10429 class BaseCAS<string order, string size, RegisterClass RC>
10430       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10431                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10432                         "$out = $Rs",[]>,
10433         Sched<[WriteAtomic]> {
10434   let NP = 1;
10437 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10438   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10439   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10440   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10441   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10444 class BaseCASP<string order, string size, RegisterOperand RC>
10445       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10446                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10447                         "$out = $Rs",[]>,
10448         Sched<[WriteAtomic]> {
10449   let NP = 0;
10452 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10453   let Sz = 0b00, Acq = Acq, Rel = Rel in
10454     def W : BaseCASP<order, "", WSeqPairClassOperand>;
10455   let Sz = 0b01, Acq = Acq, Rel = Rel in
10456     def X : BaseCASP<order, "", XSeqPairClassOperand>;
10459 let Predicates = [HasLSE] in
10460 class BaseSWP<string order, string size, RegisterClass RC>
10461       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10462           "\t$Rs, $Rt, [$Rn]","",[]>,
10463         Sched<[WriteAtomic]> {
10464   bits<2> Sz;
10465   bit Acq;
10466   bit Rel;
10467   bits<5> Rs;
10468   bits<3> opc = 0b000;
10469   bits<5> Rn;
10470   bits<5> Rt;
10471   let Inst{31-30} = Sz;
10472   let Inst{29-24} = 0b111000;
10473   let Inst{23} = Acq;
10474   let Inst{22} = Rel;
10475   let Inst{21} = 0b1;
10476   let Inst{20-16} = Rs;
10477   let Inst{15} = 0b1;
10478   let Inst{14-12} = opc;
10479   let Inst{11-10} = 0b00;
10480   let Inst{9-5} = Rn;
10481   let Inst{4-0} = Rt;
10482   let Predicates = [HasLSE];
10485 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10486   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10487   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10488   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10489   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10492 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10493 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10494       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10495           "\t$Rs, $Rt, [$Rn]","",[]>,
10496         Sched<[WriteAtomic]> {
10497   bits<2> Sz;
10498   bit Acq;
10499   bit Rel;
10500   bits<5> Rs;
10501   bits<3> opc;
10502   bits<5> Rn;
10503   bits<5> Rt;
10504   let Inst{31-30} = Sz;
10505   let Inst{29-24} = 0b111000;
10506   let Inst{23} = Acq;
10507   let Inst{22} = Rel;
10508   let Inst{21} = 0b1;
10509   let Inst{20-16} = Rs;
10510   let Inst{15} = 0b0;
10511   let Inst{14-12} = opc;
10512   let Inst{11-10} = 0b00;
10513   let Inst{9-5} = Rn;
10514   let Inst{4-0} = Rt;
10515   let Predicates = [HasLSE];
10518 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10519                         string order> {
10520   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10521     def B : BaseLDOPregister<op, order, "b", GPR32>;
10522   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10523     def H : BaseLDOPregister<op, order, "h", GPR32>;
10524   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10525     def W : BaseLDOPregister<op, order, "", GPR32>;
10526   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10527     def X : BaseLDOPregister<op, order, "", GPR64>;
10530 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10531 // complex DAG for DstRHS.
10532 let Predicates = [HasLSE] in
10533 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10534                                          string size, dag SrcRHS, dag DstRHS> {
10535   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10536             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10537   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10538             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10539   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10540             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10541   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10542             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10543   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10544             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10547 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10548                                      string size, dag RHS> {
10549   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10552 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10553                                          string size, dag LHS, dag RHS> {
10554   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10557 multiclass LDOPregister_patterns<string inst, string op> {
10558   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10559   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10560   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10561   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10564 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10565   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10566                         (i64 GPR64:$Rm),
10567                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10568   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10569                         (i32 GPR32:$Rm),
10570                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10571   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10572                         (i32 GPR32:$Rm),
10573                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10574   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10575                         (i32 GPR32:$Rm),
10576                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10579 let Predicates = [HasLSE] in
10580 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10581                                         string size, dag OLD, dag NEW> {
10582   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10583             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10584   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10585             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10586   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10587             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10588   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10589             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10590   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10591             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10594 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10595                                     string size, dag OLD, dag NEW> {
10596   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10599 multiclass CASregister_patterns<string inst, string op> {
10600   defm : CASregister_patterns_ord<inst, "X", op, "64",
10601                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10602   defm : CASregister_patterns_ord<inst, "W", op, "32",
10603                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10604   defm : CASregister_patterns_ord<inst, "H", op, "16",
10605                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10606   defm : CASregister_patterns_ord<inst, "B", op, "8",
10607                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10610 let Predicates = [HasLSE] in
10611 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10612                         Instruction inst> :
10613       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10615 multiclass STOPregister<string asm, string instr> {
10616   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10617                     !cast<Instruction>(instr # "LB")>;
10618   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10619                     !cast<Instruction>(instr # "LH")>;
10620   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10621                     !cast<Instruction>(instr # "LW")>;
10622   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10623                     !cast<Instruction>(instr # "LX")>;
10624   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10625                     !cast<Instruction>(instr # "B")>;
10626   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10627                     !cast<Instruction>(instr # "H")>;
10628   def : BaseSTOPregister<asm,        GPR32, WZR,
10629                     !cast<Instruction>(instr # "W")>;
10630   def : BaseSTOPregister<asm,        GPR64, XZR,
10631                     !cast<Instruction>(instr # "X")>;
10634 //----------------------------------------------------------------------------
10635 // Allow the size specifier tokens to be upper case, not just lower.
10636 def : TokenAlias<".4B", ".4b">;  // Add dot product
10637 def : TokenAlias<".8B", ".8b">;
10638 def : TokenAlias<".4H", ".4h">;
10639 def : TokenAlias<".2S", ".2s">;
10640 def : TokenAlias<".1D", ".1d">;
10641 def : TokenAlias<".16B", ".16b">;
10642 def : TokenAlias<".8H", ".8h">;
10643 def : TokenAlias<".4S", ".4s">;
10644 def : TokenAlias<".2D", ".2d">;
10645 def : TokenAlias<".1Q", ".1q">;
10646 def : TokenAlias<".2H", ".2h">;
10647 def : TokenAlias<".B", ".b">;
10648 def : TokenAlias<".H", ".h">;
10649 def : TokenAlias<".S", ".s">;
10650 def : TokenAlias<".D", ".d">;
10651 def : TokenAlias<".Q", ".q">;